basic working search

This commit is contained in:
Christoph J. Scherr 2023-06-03 14:40:57 +02:00
parent d6ab46f44d
commit 201e6e1654
Signed by: PlexSheep
GPG Key ID: 25B4ACF7D88186CC
15 changed files with 159 additions and 185 deletions

View File

@ -12,3 +12,5 @@ class BlogPostAdmin(admin.ModelAdmin):
""" """
The admin model for BlogPost The admin model for BlogPost
""" """
list_display = ["title_en", "subtitle_en", "title_de", "subtitle_de", "date", "category", "suburl"]
date_hierarchy = "date"

View File

@ -1,31 +1,12 @@
# Generated by Django 3.2.19 on 2023-05-31 20:54 # Generated by Django 3.2.19 on 2023-06-03 12:03
from django.db import migrations, models from django.db import migrations
class Migration(migrations.Migration): class Migration(migrations.Migration):
initial = True
dependencies = [ dependencies = [
('start', '0002_auto_20230531_2254'),
] ]
operations = [ operations = [
migrations.CreateModel(
name='BlogPost',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('title', models.CharField(max_length=50)),
('subtitle', models.CharField(max_length=50)),
('desc', models.CharField(max_length=250, unique=True)),
('body', models.TextField()),
('date', models.DateField(blank=True)),
('slug', models.SlugField()),
('keywords', models.ManyToManyField(to='start.Keyword')),
],
options={
'abstract': False,
},
),
] ]

View File

@ -1,36 +0,0 @@
# Generated by Django 3.2.19 on 2023-06-02 10:00
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
('start', '0002_auto_20230531_2254'),
('blog', '0001_initial'),
]
operations = [
migrations.CreateModel(
name='Category',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('title', models.CharField(max_length=50)),
('subtitle', models.CharField(max_length=50)),
('desc', models.CharField(max_length=250, unique=True)),
('date', models.DateField(blank=True)),
('name', models.CharField(max_length=50)),
('slug', models.SlugField()),
('keywords', models.ManyToManyField(to='start.Keyword')),
],
options={
'abstract': False,
},
),
migrations.AddField(
model_name='blogpost',
name='category',
field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, to='blog.category'),
),
]

View File

@ -0,0 +1,35 @@
# Generated by Django 3.2.19 on 2023-06-03 12:03
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
initial = True
dependencies = [
('start', '0002_keyword_searchable_staticsite'),
('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()),
],
),
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', models.TextField()),
('thumbnail', models.ImageField(blank=True, upload_to='')),
('category', models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, to='blog.category')),
],
bases=('start.searchable',),
),
]

View File

@ -1,38 +0,0 @@
# Generated by Django 3.2.19 on 2023-06-02 22:09
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('blog', '0002_auto_20230602_1200'),
]
operations = [
migrations.RemoveField(
model_name='category',
name='date',
),
migrations.RemoveField(
model_name='category',
name='desc',
),
migrations.RemoveField(
model_name='category',
name='keywords',
),
migrations.RemoveField(
model_name='category',
name='subtitle',
),
migrations.RemoveField(
model_name='category',
name='title',
),
migrations.AddField(
model_name='blogpost',
name='thumbnail',
field=models.ImageField(blank=True, upload_to=''),
),
]

View File

@ -1,6 +1,6 @@
from django.db import models from django.db import models
from start.models import AbstractSearchable from start.models import Searchable
class Category(models.Model): class Category(models.Model):
""" """
@ -9,15 +9,10 @@ class Category(models.Model):
name = models.CharField(max_length=50) name = models.CharField(max_length=50)
slug = models.SlugField() slug = models.SlugField()
class BlogPost(AbstractSearchable): class BlogPost(Searchable):
""" """
Should contain a blogpost Should contain a blogpost
""" """
title = models.CharField(max_length=50)
subtitle = models.CharField(max_length=50)
desc = models.CharField(max_length=250, unique=True)
body = models.TextField() body = models.TextField()
date = models.DateField(blank=True)
category = models.ForeignKey(Category, on_delete=models.SET_NULL, null=True) category = models.ForeignKey(Category, on_delete=models.SET_NULL, null=True)
thumbnail = models.ImageField(blank=True) thumbnail = models.ImageField(blank=True)
slug = models.SlugField()

View File

@ -1,3 +1,18 @@
from django.contrib import admin from django.contrib import admin
from django.db.models import CASCADE, AutoField, OneToOneField
from django.views.generic import View
from .models import *
# Register your models here. @admin.register(Keyword)
class KeywordAdmin(admin.ModelAdmin):
"""
Admin Interface for Keyword
"""
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"]

View File

@ -1,25 +1,12 @@
# Generated by Django 3.2.19 on 2023-05-30 17:08 # Generated by Django 3.2.19 on 2023-06-03 12:03
from django.db import migrations, models from django.db import migrations
class Migration(migrations.Migration): class Migration(migrations.Migration):
initial = True
dependencies = [ dependencies = [
] ]
operations = [ operations = [
migrations.CreateModel(
name='MainSearchEntry',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('title', models.CharField(max_length=50)),
('subtitle', models.CharField(max_length=50)),
('desc', models.CharField(max_length=250, unique=True)),
('date', models.DateField(blank=True)),
('link', models.URLField()),
],
),
] ]

View File

@ -1,37 +0,0 @@
# Generated by Django 3.2.19 on 2023-05-31 20:54
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('start', '0001_initial'),
]
operations = [
migrations.CreateModel(
name='Keyword',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('text', models.CharField(max_length=40)),
],
),
migrations.CreateModel(
name='StaticSite',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('title', models.CharField(max_length=50)),
('subtitle', models.CharField(max_length=50)),
('desc', models.CharField(max_length=250, unique=True)),
('date', models.DateField(blank=True)),
('keywords', models.ManyToManyField(to='start.Keyword')),
],
options={
'abstract': False,
},
),
migrations.DeleteModel(
name='MainSearchEntry',
),
]

View File

@ -0,0 +1,46 @@
# Generated by Django 3.2.19 on 2023-06-03 12:03
from django.db import migrations, models
import django.db.models.deletion
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')),
('text_de', models.CharField(max_length=40)),
('text_en', models.CharField(max_length=40)),
],
),
migrations.CreateModel(
name='Searchable',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('title_de', models.CharField(default='Titel DE', max_length=50)),
('title_en', models.CharField(default='title en', max_length=50)),
('subtitle_de', models.CharField(blank=True, max_length=50)),
('subtitle_en', models.CharField(blank=True, max_length=50)),
('desc_de', models.CharField(default='Beschreibung DE', max_length=250, unique=True)),
('desc_en', models.CharField(default='Description EN', max_length=250, unique=True)),
('date', models.DateField(blank=True, null=True)),
('suburl', models.CharField(blank=True, max_length=200, null=True)),
('keywords', models.ManyToManyField(to='start.Keyword')),
],
),
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')),
],
bases=('start.searchable',),
),
]

View File

@ -8,25 +8,26 @@ class Keyword(models.Model):
""" """
this is the model that should contain searchable keywords this is the model that should contain searchable keywords
""" """
text = models.CharField(max_length=40) text_de = models.CharField(max_length=40)
text_en = models.CharField(max_length=40)
class AbstractSearchable(models.Model): class Searchable(models.Model):
""" """
Abstract class for any model that should be searchable. 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 model will be searched for by the searchbox that is in every upper part of the website.
"""
title = models.CharField(max_length=50)
subtitle = models.CharField(max_length=50)
desc = models.CharField(max_length=250, unique=True)
# may be empty/blank for some entries
date = models.DateField(blank=True)
keywords = models.ManyToManyField(Keyword)
class Meta: This class is not a real abstract class, I need to query it in the main search, so thats impossible
""" """
AbstractSearchable is an abstract model title_de = models.CharField(max_length=50, default="Titel DE")
""" title_en = models.CharField(max_length=50, default="title en")
abstract = True subtitle_de = models.CharField(max_length=50, blank=True)
subtitle_en = models.CharField(max_length=50, blank=True)
desc_de = models.CharField(max_length=250, unique=True, default="Beschreibung DE")
desc_en = models.CharField(max_length=250, unique=True, default="Description EN")
# may be empty/blank for some entries
date = models.DateField(blank=True, null=True)
keywords = models.ManyToManyField(Keyword)
suburl = models.CharField(max_length=200, blank=True, null=True)
@classmethod @classmethod
def regenerate_all_entries(cls): def regenerate_all_entries(cls):
@ -35,7 +36,7 @@ class AbstractSearchable(models.Model):
""" """
raise NotImplementedError raise NotImplementedError
class StaticSite(AbstractSearchable): class StaticSite(Searchable):
""" """
This model represents any static site, such as start:index, This model represents any static site, such as start:index,
that should show up in search. that should show up in search.

View File

@ -1,4 +1,4 @@
{% extends 'start/base.html' %} {% extends 'base.html' %}
{% load i18n %} {% load i18n %}
{% get_current_language as LANGUAGE_CODE %} {% get_current_language as LANGUAGE_CODE %}
{% block languagecode %}{{ LANGUAGE_CODE }}{% endblock languagecode %} {% block languagecode %}{{ LANGUAGE_CODE }}{% endblock languagecode %}
@ -8,4 +8,8 @@
<h1>{% translate "Bad request" %}</h1> <h1>{% translate "Bad request" %}</h1>
<p>{% translate "You fucked up" %}</p> <p>{% translate "You fucked up" %}</p>
</div> </div>
<div class="container text-center jumbotron my-5" py-5>
<h1 class="my-4">{% translate "Looking for anything specific?" %}</h1>
{% include 'main_search_form.html' %}
</div>
{% endblock main %} {% endblock main %}

View File

@ -6,12 +6,21 @@
{% block main %} {% block main %}
<div class="container-xxl"> <div class="container-xxl">
<div class="jumbotron text-center"> <div class="jumbotron text-center">
<h1>{% translate "Search for:" %} {{ searchstr }}</h1> <h1>{% translate "Search for:" %} {{ request.GET }}</h1>
</div> </div>
<div class="row text-center"> <div class="row">
<div class="col"> {% for result in object_list %}
I don't know what to put here <div class="card m-2">
<div class="card-header">
{{ result.title_de }}
</div> </div>
<div class="card-body">
<h5 class="card-title">{{ result.subtitle_de }}</h5>
<p class="card-text">{{result.desc_de}}</p>
<a href="/{{ LANGUAGE_CODE }}{{ result.suburl }}" class="btn btn-primary">Go somewhere</a>
</div>
</div>
{% endfor %}
</div> </div>
</div> </div>
{% endblock main %} {% endblock main %}

View File

@ -1,4 +1,5 @@
from http.client import HTTPResponse from http.client import HTTPResponse
from typing import List
from django.shortcuts import redirect from django.shortcuts import redirect
from django.utils import translation from django.utils import translation
from django.views.generic.base import View from django.views.generic.base import View
@ -10,9 +11,11 @@ from django.views import View
from django.template import Template, context, loader from django.template import Template, context, loader
from django.http import HttpResponseRedirect from django.http import HttpResponseRedirect
from django.shortcuts import render from django.shortcuts import render
from django.views.generic.list import QuerySet
from django.db.models import Q
from .forms import MainSearchForm from .forms import MainSearchForm
from .models import AbstractSearchable from .models import Searchable
from abc import ABC from abc import ABC
@ -71,16 +74,22 @@ class MainSearch(ListView):
Search for anything. Search for anything.
""" """
model = AbstractSearchable model = Searchable
object_list = [] # this is only declaration, the view breaks without it. object_list = [] # this is only declaration, the view breaks without it.
template_name: str = "start/search.html" 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)
)
print(object_list)
return object_list
def get(self, request, *args, **kwargs): def get(self, request, *args, **kwargs):
form = MainSearchForm(request.GET) form = MainSearchForm(request.GET)
if not form.is_valid(): if not form.is_valid():
return render(request, "errors/bad_request.html") return render(request, "errors/bad_request.html")
return super().get(request, *args, **kwargs)
context = self.get_context_data(**kwargs)
context["searchstr"] = form.cleaned_data['search']
#object_list = self.model.objects.filter("something")
return render(request=request, template_name=self.template_name, context=context)

View File

@ -3,3 +3,4 @@ psycopg2>=2.8
mysqlclient>=1.4.3 mysqlclient>=1.4.3
django_compressor>=2.2 django_compressor>=2.2
django-libsass>=0.7 django-libsass>=0.7
pillow>=9.0.0