remove searchable model

This commit is contained in:
Christoph J. Scherr 2023-10-10 12:00:31 +02:00
parent e868e0ccee
commit 4e322f7211
19 changed files with 186 additions and 347 deletions

View File

@ -12,12 +12,6 @@ class CategoryAdmin(admin.ModelAdmin):
list_display = ["name", "slug"]
@admin.action(description=_("Regenerate traits"))
def regenerate(modeladmin, request, queryset):
for obj in queryset:
obj.regenerate()
@admin.register(BlogPost)
class BlogPostAdmin(admin.ModelAdmin):
"""
@ -26,8 +20,6 @@ class BlogPostAdmin(admin.ModelAdmin):
list_display = ["title_en", "subtitle_en", "title_de", "subtitle_de", "date", "category", "slug", "suburl", "public"]
date_hierarchy = "date"
ordering = ['title_de', 'title_en']
actions = [regenerate]
change_list_template = "admin/blogpost.html"
def get_urls(self):

View File

@ -1,47 +1,12 @@
# Generated by Django 3.2.21 on 2023-10-02 08:14
# Generated by Django 4.2.6 on 2023-10-10 09:58
import blog.models
from django.db import migrations, models
import django.db.models.deletion
from django.db import migrations
class Migration(migrations.Migration):
initial = True
dependencies = [
('start', '0001_initial'),
]
operations = [
migrations.CreateModel(
name='Category',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('name', models.CharField(max_length=50)),
('slug', models.SlugField(unique=True)),
],
options={
'verbose_name': 'Category',
'verbose_name_plural': 'Categories',
},
),
migrations.CreateModel(
name='BlogPost',
fields=[
('searchable_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='start.searchable')),
('body_en', models.TextField(blank=True, default='Dieser Artikel ist nicht auf deutsch verfügbar.')),
('body_de', models.TextField(blank=True, default='This aritcle is not available in english.')),
('thumbnail', models.ImageField(blank=True, default='img/thumbnails/default.jpg', upload_to='img/thumbnails')),
('featured', models.BooleanField(default=False)),
('langs', models.CharField(default="{'en': False, 'de': False}", max_length=64)),
('slug', models.SlugField()),
('category', models.ForeignKey(default=blog.models.Category.get_or_create_uncategorized, on_delete=django.db.models.deletion.SET_DEFAULT, to='blog.category')),
],
options={
'verbose_name': 'blog post',
'verbose_name_plural': 'blog posts',
},
bases=('start.searchable',),
),
]

View File

@ -1,18 +0,0 @@
# Generated by Django 4.2.5 on 2023-10-02 19:03
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('blog', '0001_initial'),
]
operations = [
migrations.AlterField(
model_name='blogpost',
name='slug',
field=models.SlugField(unique=True),
),
]

View File

@ -0,0 +1,58 @@
# Generated by Django 4.2.6 on 2023-10-10 09:58
import blog.models
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
initial = True
dependencies = [
('start', '0002_initial'),
('blog', '0001_initial'),
]
operations = [
migrations.CreateModel(
name='Category',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('name', models.CharField(max_length=50)),
('slug', models.SlugField(unique=True)),
],
options={
'verbose_name': 'Category',
'verbose_name_plural': 'Categories',
},
),
migrations.CreateModel(
name='BlogPost',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('body_en', models.TextField(blank=True, default='Dieser Artikel ist nicht auf deutsch verfügbar.')),
('body_de', models.TextField(blank=True, default='This aritcle is not available in english.')),
('thumbnail', models.ImageField(blank=True, default='img/thumbnails/default.jpg', upload_to='img/thumbnails')),
('featured', models.BooleanField(default=False)),
('langs', models.CharField(default="{'en': False, 'de': False}", max_length=64)),
('slug', models.SlugField(unique=True)),
('title_de', models.CharField(default='Nicht übersetzt', max_length=50)),
('title_en', models.CharField(default='Not translated', max_length=50)),
('subtitle_de', models.CharField(blank=True, max_length=50)),
('subtitle_en', models.CharField(blank=True, max_length=50)),
('desc_de', models.TextField(blank=True, default='Keine Beschreibung', max_length=250)),
('desc_en', models.TextField(blank=True, default='no description', max_length=250)),
('date', models.DateTimeField(blank=True, null=True)),
('update', models.DateTimeField(blank=True, null=True)),
('suburl', models.CharField(blank=True, max_length=200, null=True)),
('public', models.BooleanField(default=False)),
('category', models.ForeignKey(default=blog.models.Category.get_or_create_uncategorized, on_delete=django.db.models.deletion.SET_DEFAULT, to='blog.category')),
('keywords', models.ManyToManyField(blank=True, to='start.keyword')),
],
options={
'verbose_name': 'blog post',
'verbose_name_plural': 'blog posts',
},
),
]

View File

@ -7,7 +7,7 @@ import markdown
from bs4 import BeautifulSoup
from django.db import models
from django.utils.translation import gettext as _
from start.models import Keyword, Searchable
from start.models import Keyword
import logging
logger = logging.getLogger(__name__)
@ -56,7 +56,7 @@ class Category(models.Model):
slug="uncategorized", name="uncategorized")
class BlogPost(Searchable):
class BlogPost(models.Model):
"""
Should contain a blogpost
"""
@ -87,6 +87,19 @@ class BlogPost(Searchable):
langs = models.CharField(
default=DEFAULT_LANGS.__repr__(), max_length=64)
slug = models.SlugField(unique=True, blank=False)
title_de = models.CharField(max_length=50, default="Nicht übersetzt")
title_en = models.CharField(max_length=50, default="Not translated")
subtitle_de = models.CharField(max_length=50, blank=True)
subtitle_en = models.CharField(max_length=50, blank=True)
desc_de = models.TextField(
blank=True, max_length=250, unique=False, default="Keine Beschreibung")
desc_en = models.TextField(
blank=True, max_length=250, unique=False, default="no description")
date = models.DateTimeField(blank=True, null=True)
update = models.DateTimeField(blank=True, null=True)
keywords = models.ManyToManyField(Keyword, blank=True)
suburl = models.CharField(max_length=200, blank=True, null=True)
public = models.BooleanField(default=False)
def save(self):
# check if the slug is empty if we remove whitespaces

View File

@ -43,14 +43,12 @@
</div>
</div>
<div class="container text-center jumbotron my-3">
<h1 class="my-4">{% translate "Looking for anything specific?" %}</h1>
{% include 'main_search_form.html' %}
<h4 class="my-5">
<h2 class="my-5">
<a href="{% url 'blog:browse' %}"
class="link-offset-2 link-underline link-underline-opacity-0">
{% translate "Browse posts" %}
</a>
</h4>
</h2>
</div>
{% include 'blog/featured.html' %}
</div>

View File

@ -9,13 +9,11 @@ from django.views.generic import TemplateView, DetailView, ListView, View
from django.db.models import Q
from .models import BlogPost, Category, Keyword
from start.views import SearchableView
import logging
logger = logging.getLogger(__name__)
class Index(TemplateView, SearchableView):
class Index(TemplateView):
"""
The index page of the gawa/blog app.
@ -51,7 +49,6 @@ class Browse(ListView):
Scroll through a list of blog posts
There should also be some kind of filter, for category and date.
Of course, Articles will also show up in the MainSearchView
"""
model = BlogPost

Binary file not shown.

View File

@ -8,7 +8,7 @@ msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2023-10-09 23:19+0200\n"
"POT-Creation-Date: 2023-10-10 11:46+0200\n"
"PO-Revision-Date: 2023-10-08 21:03+0200\n"
"Last-Translator: <software@cscherr.de>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
@ -19,10 +19,6 @@ msgstr ""
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
"X-Translated-Using: django-rosetta 0.9.9\n"
#: blog/admin.py:15 start/admin.py:8
msgid "Regenerate traits"
msgstr "Eigenschaften regenerieren"
#: blog/models.py:44
msgid "Category"
msgstr "Kategorie"
@ -31,11 +27,11 @@ msgstr "Kategorie"
msgid "Categories"
msgstr "Kategorien"
#: blog/models.py:282
#: blog/models.py:295
msgid "blog post"
msgstr "Blog Post"
#: blog/models.py:283
#: blog/models.py:296
msgid "blog posts"
msgstr "Blog Posts"
@ -65,7 +61,6 @@ msgid "updated"
msgstr "aktualisiert"
#: blog/templates/blog/browse.html:47 start/forms.py:15
#: start/templates/main_search_form.html:3
msgid "Search"
msgstr "Suche"
@ -156,11 +151,7 @@ msgstr ""
"\n"
"Das ist mein persönlicher Blog. Ich lade hier hoch was auch immer ich möchte."
#: blog/templates/blog/index.html:46
msgid "Looking for anything specific?"
msgstr "Suchst du nach etwas speziellem?"
#: blog/templates/blog/index.html:51
#: blog/templates/blog/index.html:49
msgid "Browse posts"
msgstr "Posts durchsuchen"
@ -172,6 +163,10 @@ msgstr "Deutsch"
msgid "English"
msgstr "Englisch"
#: start/admin.py:8
msgid "Regenerate traits"
msgstr "Eigenschaften regenerieren"
#: start/models.py:27
msgid "Keyword"
msgstr "Schlüsselwort"
@ -180,27 +175,11 @@ msgstr "Schlüsselwort"
msgid "keywords"
msgstr "Schlüsselwörter"
#: start/models.py:72
msgid "Searchable"
msgstr "suchbares Objekt"
#: start/models.py:73
msgid "Searchables"
msgstr "suchbare Objekte"
#: start/models.py:95
msgid "static site"
msgstr "statische Seite"
#: start/models.py:96
msgid "static sites"
msgstr "statische Seiten"
#: start/models.py:165
#: start/models.py:109
msgid "Link"
msgstr "Link"
#: start/models.py:166 start/templates/nav.html:36
#: start/models.py:110 start/templates/nav.html:36
#: start/templates/start/legalinfo.html:8 start/templates/start/links.html:5
msgid "Links"
msgstr "Links"
@ -281,10 +260,6 @@ msgstr "Kontakt"
msgid "Deutschland"
msgstr "Deutschland"
#: start/templates/main_search_form.html:4
msgid "Go"
msgstr "Los"
#: start/templates/nav.html:27 start/templates/nav.html:30
#: start/templates/nav.html:54
msgid "Start"
@ -544,6 +519,24 @@ msgstr "Andere"
msgid "Search for"
msgstr "Suche nach"
#~ msgid "Looking for anything specific?"
#~ msgstr "Suchst du nach etwas speziellem?"
#~ msgid "Searchable"
#~ msgstr "suchbares Objekt"
#~ msgid "Searchables"
#~ msgstr "suchbare Objekte"
#~ msgid "static site"
#~ msgstr "statische Seite"
#~ msgid "static sites"
#~ msgstr "statische Seiten"
#~ msgid "Go"
#~ msgstr "Los"
#~ msgid "Email "
#~ msgstr "E-Mail"

View File

@ -7,7 +7,7 @@ msgid ""
msgstr ""
"Project-Id-Version: \n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2023-10-09 23:19+0200\n"
"POT-Creation-Date: 2023-10-10 11:46+0200\n"
"PO-Revision-Date: 2023-10-08 15:18+0200\n"
"Last-Translator: \n"
"Language-Team: \n"
@ -18,10 +18,6 @@ msgstr ""
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
"X-Generator: Poedit 3.3.2\n"
#: blog/admin.py:15 start/admin.py:8
msgid "Regenerate traits"
msgstr ""
#: blog/models.py:44
msgid "Category"
msgstr ""
@ -30,11 +26,11 @@ msgstr ""
msgid "Categories"
msgstr ""
#: blog/models.py:282
#: blog/models.py:295
msgid "blog post"
msgstr ""
#: blog/models.py:283
#: blog/models.py:296
msgid "blog posts"
msgstr ""
@ -64,7 +60,6 @@ msgid "updated"
msgstr ""
#: blog/templates/blog/browse.html:47 start/forms.py:15
#: start/templates/main_search_form.html:3
msgid "Search"
msgstr ""
@ -144,11 +139,7 @@ msgid ""
" "
msgstr ""
#: blog/templates/blog/index.html:46
msgid "Looking for anything specific?"
msgstr ""
#: blog/templates/blog/index.html:51
#: blog/templates/blog/index.html:49
msgid "Browse posts"
msgstr ""
@ -160,6 +151,10 @@ msgstr ""
msgid "English"
msgstr ""
#: start/admin.py:8
msgid "Regenerate traits"
msgstr ""
#: start/models.py:27
msgid "Keyword"
msgstr ""
@ -168,27 +163,11 @@ msgstr ""
msgid "keywords"
msgstr ""
#: start/models.py:72
msgid "Searchable"
msgstr ""
#: start/models.py:73
msgid "Searchables"
msgstr ""
#: start/models.py:95
msgid "static site"
msgstr ""
#: start/models.py:96
msgid "static sites"
msgstr ""
#: start/models.py:165
#: start/models.py:109
msgid "Link"
msgstr ""
#: start/models.py:166 start/templates/nav.html:36
#: start/models.py:110 start/templates/nav.html:36
#: start/templates/start/legalinfo.html:8 start/templates/start/links.html:5
msgid "Links"
msgstr ""
@ -262,10 +241,6 @@ msgstr "Contact"
msgid "Deutschland"
msgstr "Germany"
#: start/templates/main_search_form.html:4
msgid "Go"
msgstr ""
#: start/templates/nav.html:27 start/templates/nav.html:30
#: start/templates/nav.html:54
msgid "Start"

View File

@ -19,28 +19,6 @@ class KeywordAdmin(admin.ModelAdmin):
list_display = ["text_en", "text_de"]
@admin.register(StaticSite)
class StaticSiteAdmin(admin.ModelAdmin):
"""
Admin Interface for StaticSite
"""
list_display = ["title_en", "subtitle_en",
"title_de", "subtitle_de", "suburl"]
ordering = ['title_de', 'title_en']
actions = [regenerate]
@admin.register(Searchable)
class SearchableAdmin(admin.ModelAdmin):
"""
Abstract Admin Interface for all Searchables
"""
list_display = ["title_en", "subtitle_en",
"title_de", "subtitle_de", "suburl"]
ordering = ['title_de', 'title_en']
actions = [regenerate]
@admin.register(Link)
class LinkAdmin(admin.ModelAdmin):
"""

View File

@ -1,75 +1,12 @@
# Generated by Django 3.2.21 on 2023-10-02 08:14
# Generated by Django 4.2.6 on 2023-10-10 09:58
from django.db import migrations, models
import django.db.models.deletion
from django.db import migrations
class Migration(migrations.Migration):
initial = True
dependencies = [
]
operations = [
migrations.CreateModel(
name='Keyword',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('slug', models.SlugField(unique=True)),
('text_de', models.CharField(max_length=40)),
('text_en', models.CharField(max_length=40)),
],
options={
'verbose_name': 'Keyword',
'verbose_name_plural': 'keywords',
},
),
migrations.CreateModel(
name='Searchable',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('title_de', models.CharField(default='Nicht übersetzt', max_length=50)),
('title_en', models.CharField(default='Not translated', max_length=50)),
('subtitle_de', models.CharField(blank=True, max_length=50)),
('subtitle_en', models.CharField(blank=True, max_length=50)),
('desc_de', models.TextField(blank=True, default='Keine Beschreibung', max_length=250)),
('desc_en', models.TextField(blank=True, default='no description', max_length=250)),
('date', models.DateTimeField(blank=True, null=True)),
('update', models.DateTimeField(blank=True, null=True)),
('suburl', models.CharField(blank=True, max_length=200, null=True)),
('public', models.BooleanField(default=False)),
('keywords', models.ManyToManyField(blank=True, to='start.Keyword')),
],
options={
'verbose_name': 'Searchable',
'verbose_name_plural': 'Searchables',
},
),
migrations.CreateModel(
name='Link',
fields=[
('searchable_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, to='start.searchable')),
('url', models.URLField(primary_key=True, serialize=False, unique=True)),
('favicon', models.ImageField(blank=True, null=True, upload_to='img/links/favicons')),
('status', models.BooleanField(default=False)),
('personal', models.BooleanField(default=False)),
],
options={
'verbose_name': 'Link',
'verbose_name_plural': 'Links',
},
bases=('start.searchable',),
),
migrations.CreateModel(
name='StaticSite',
fields=[
('searchable_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='start.searchable')),
],
options={
'verbose_name': 'static site',
'verbose_name_plural': 'static sites',
},
bases=('start.searchable',),
),
]

View File

@ -0,0 +1,52 @@
# Generated by Django 4.2.6 on 2023-10-10 09:58
from django.db import migrations, models
class Migration(migrations.Migration):
initial = True
dependencies = [
('start', '0001_initial'),
]
operations = [
migrations.CreateModel(
name='Keyword',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('slug', models.SlugField(unique=True)),
('text_de', models.CharField(max_length=40)),
('text_en', models.CharField(max_length=40)),
],
options={
'verbose_name': 'Keyword',
'verbose_name_plural': 'keywords',
},
),
migrations.CreateModel(
name='Link',
fields=[
('url', models.URLField(primary_key=True, serialize=False, unique=True)),
('favicon', models.ImageField(blank=True, null=True, upload_to='img/links/favicons')),
('status', models.BooleanField(default=False)),
('personal', models.BooleanField(default=False)),
('title_de', models.CharField(default='Nicht übersetzt', max_length=50)),
('title_en', models.CharField(default='Not translated', max_length=50)),
('subtitle_de', models.CharField(blank=True, max_length=50)),
('subtitle_en', models.CharField(blank=True, max_length=50)),
('desc_de', models.TextField(blank=True, default='Keine Beschreibung', max_length=250)),
('desc_en', models.TextField(blank=True, default='no description', max_length=250)),
('date', models.DateTimeField(blank=True, null=True)),
('update', models.DateTimeField(blank=True, null=True)),
('suburl', models.CharField(blank=True, max_length=200, null=True)),
('public', models.BooleanField(default=False)),
('keywords', models.ManyToManyField(blank=True, to='start.keyword')),
],
options={
'verbose_name': 'Link',
'verbose_name_plural': 'Links',
},
),
]

View File

@ -27,14 +27,17 @@ class Keyword(models.Model):
verbose_name = _("Keyword")
verbose_name_plural = _("keywords")
class Searchable(models.Model):
class Link(models.Model):
"""
Abstract class for any model that should be searchable.
This model will be searched for by the searchbox that is in every upper part of the website.
This class is not a real abstract class, I need to query it in the main search, so thats impossible
contains all my interesting links
"""
# the actual link
url = models.URLField(unique=True, null=False, primary_key=True)
favicon_dir: str = "img/links/favicons"
favicon = models.ImageField(blank=True, upload_to=favicon_dir, null=True)
status = models.BooleanField(default=False)
personal = models.BooleanField(default=False)
title_de = models.CharField(max_length=50, default="Nicht übersetzt")
title_en = models.CharField(max_length=50, default="Not translated")
subtitle_de = models.CharField(max_length=50, blank=True)
@ -49,65 +52,6 @@ class Searchable(models.Model):
suburl = models.CharField(max_length=200, blank=True, null=True)
public = models.BooleanField(default=False)
@classmethod
def regenerate_all_entries(cls):
"""
regenerate all searchable items
"""
logger.info(f"regenerating all {Searchable.__name__} entries")
for obj in cls.objects.all():
obj.regenerate()
def __str__(self):
return f"{{<{self.__class__.__name__}>\"{self.title_en}\"}}"
def regenerate(self):
"""
regenerate a object
"""
raise NotImplementedError(
f"{self.__class__.__name__} does not implement regenerate")
class Meta:
verbose_name = _("Searchable")
verbose_name_plural = _("Searchables")
class StaticSite(Searchable):
"""
This model represents any static site, such as start:index,
that should show up in search.
Every searchable view should inherit from start.views.SearchableView.
# TODO automate scanning for SearchableView classes
"""
def regenerate(self):
"""
regenerate a object
"""
logger.info(f"regenerating {self.__class__.__name__} object: {self}")
logger.warning(f"{self.__class__.__name__} cannot regenerate.")
# self.save()
pass
class Meta:
verbose_name = _("static site")
verbose_name_plural = _("static sites")
class Link(Searchable):
"""
contains all my interesting links
"""
# the actual link
url = models.URLField(unique=True, null=False, primary_key=True)
favicon_dir: str = "img/links/favicons"
favicon = models.ImageField(blank=True, upload_to=favicon_dir, null=True)
status = models.BooleanField(default=False)
personal = models.BooleanField(default=False)
def __str__(self):
return f"{{<{self.__class__.__name__}>\"{self.title_en}\"}}"

View File

@ -1,5 +0,0 @@
{% load i18n %}
<form class="d-flex" role="search" action="{% url 'start:search' %}" method="GET">
<input type="search" name="search" class="form-control me-2" aria-label="Search" placeholder="{% trans "Search" %}" required id="id_search">
<button class="btn bg-primary fw-bold" type="submit">{% translate "Go" %}</button>
</form>

View File

@ -119,7 +119,6 @@
{% endif %}
</ul>
</li>
<li class="nav-item dropdown">{% include 'main_search_form.html' %}</li>
</ul>
</div>
</div>

View File

@ -5,7 +5,6 @@ from . import views
app_name: str = "start"
urlpatterns = [
path("", views.Index.as_view(), name="index"),
path("search/", views.MainSearch.as_view(), name="search"),
path("reporting/", views.Reporting.as_view(), name="reporting"),
path("legal/", views.LegalInfo.as_view(), name="legal"),
path("links/", views.Links.as_view(), name="links"),

View File

@ -11,8 +11,7 @@ from django.views.static import loader
from django.views import i18n
from requests import request
from .forms import MainSearchForm
from .models import Link, Searchable
from .models import Link
from abc import ABC
@ -20,19 +19,7 @@ import logging
logger = logging.getLogger(__name__)
class SearchableView(View, ABC):
"""
This abstract view implements some traits of views that should show up
in the main search
"""
title: str
subtitle: str
desc: str
date: None = None
keywords: list[str]
class Index(TemplateView, SearchableView):
class Index(TemplateView):
"""
The index page of the gawa app.
@ -43,7 +30,7 @@ class Index(TemplateView, SearchableView):
template_name: str = "start/index.html"
class Professional(TemplateView, SearchableView):
class Professional(TemplateView):
"""
Professional informations that might interest a professional employer
"""
@ -51,7 +38,7 @@ class Professional(TemplateView, SearchableView):
template_name: str = "start/legalinfo.html"
class Reporting(TemplateView, SearchableView):
class Reporting(TemplateView):
"""
Reporting Interface and information about the allowed scope of searching for
security issues.
@ -59,39 +46,14 @@ class Reporting(TemplateView, SearchableView):
# TODO
template_name: str = "start/reporting.html"
class LegalInfo(TemplateView, SearchableView):
class LegalInfo(TemplateView):
"""
Legal info that the german authorities want.
"""
# TODO
template_name: str = "start/legalinfo.html"
class MainSearch(ListView):
"""
Search for anything.
"""
model = Searchable
object_list = [] # this is only declaration, the view breaks without it.
template_name: str = "start/search.html"
def get_queryset(self) -> QuerySet:
search = self.request.GET.get("search")
object_list = Searchable.objects.filter(
Q(title_de__icontains=search) | Q(title_en__icontains=search) |
Q(subtitle_de__icontains=search) | Q(subtitle_en__icontains=search) |
Q(desc_de__icontains=search) | Q(desc_en__icontains=search) |
Q(public=True)
)
object_list = object_list.filter(public=True)
return object_list
def get(self, request, *args, **kwargs):
form = MainSearchForm(request.GET)
if not form.is_valid():
return render(request, "errors/bad_request.html")
return super().get(request, *args, **kwargs)
class Links(ListView):
"""