implementation for searching something in 'News' and 'Intern'

This commit is contained in:
2022-04-06 13:32:05 +00:00
parent cf632b1b31
commit df413d6814
14 changed files with 228 additions and 6 deletions

View File

@@ -31,4 +31,14 @@ docker-compose up
Mittels diesen Command können die Thumbs für die Alben in der Galerie erstellt werden:
<code>
python3 fet2020/manage.py create_thumbs
</code>
</code>
Erstellt alle Searchindexes neu.
<code>
python3 fet2020/manage.py rebuild_index
</code>
Aktualisiert alle Searchindexes, die in den letzten 24 Stunden geändert wurden.
<code>
python3 fet2020/manage.py update_index --age=24
</code>

View File

@@ -66,7 +66,7 @@ INSTALLED_APPS = [
"django.contrib.sites",
"django.contrib.sitemaps",
"django.contrib.flatpages",
"taggit",
"ckeditor",
"ckeditor_uploader",
@@ -77,7 +77,9 @@ INSTALLED_APPS = [
"django_filters",
"django_static_jquery_ui",
"fontawesomefree",
"whoosh",
"haystack",
"core.apps.CoreConfig",
"posts.apps.PostsConfig",
"members.apps.MembersConfig",
@@ -344,3 +346,12 @@ GALLERY = {
CSRF_TRUSTED_ORIGINS = [
"https://" + env("HOST_NAME"),
]
# DJANGO HAYSTACK
HAYSTACK_CONNECTIONS = {
"default": {
"ENGINE": "haystack.backends.whoosh_backend.WhooshEngine",
"PATH": os.path.join(BASE_DIR, "whoosh_index"),
},
}

View File

@@ -41,6 +41,7 @@ urlpatterns = [
path("members/", include("members.urls"), name="members"),
path("member/", include(member_urlpatterns), name="member"),
path("posts/", include("posts.urls")),
path("search/", include("search.urls")),
path("tasks/", include("tasks.urls"), name="tasks"),
path("intern/", include("intern.urls"), name="intern"),
path(

View File

@@ -9,7 +9,8 @@ from django.utils import timezone
from django.utils.text import slugify
from django.utils.translation import gettext_lazy as _
from documents import create_pad
from documents import create_pad, get_pad_html
from documents.api import get_pad_link
from tasks.models import TaskList
logger = logging.getLogger(__name__)
@@ -139,6 +140,12 @@ class Etherpad(models.Model):
),
]
def __str__(self):
return self.title
def get_absolute_url(self):
return get_pad_link(self.__get_pad_name())
def __get_pad_name(self):
return (
slugify(self.date)
@@ -170,8 +177,12 @@ class Etherpad(models.Model):
_(f"Etherpad '{pad_name}' konnte nicht erstellt werden."),
)
def __str__(self):
return self.title
@property
def etherpad_html(self):
if not self.__get_pad_name():
return None
return get_pad_html(self.__get_pad_name())
class FileUpload(models.Model):

View File

@@ -0,0 +1,17 @@
from haystack import indexes
from html2text import html2text
from .models import Etherpad
class EtherpadIndex(indexes.SearchIndex, indexes.Indexable):
text = indexes.CharField(document=True, use_template=True)
title = indexes.CharField(model_attr="title")
date = indexes.DateField(model_attr="date")
etherpad = indexes.EdgeNgramField(null=True)
def get_model(self):
return Etherpad
def prepare_etherpad(self, obj):
return html2text(obj.etherpad_html)

View File

@@ -0,0 +1,38 @@
from haystack import indexes
from html2text import html2text
from .models import Post
class PostIndex(indexes.SearchIndex, indexes.Indexable):
text = indexes.CharField(document=True, use_template=True)
title = indexes.EdgeNgramField(model_attr="title")
body = indexes.EdgeNgramField(model_attr="body", null=True)
status = indexes.EdgeNgramField(model_attr="status")
date = indexes.DateField()
agenda = indexes.EdgeNgramField(null=True)
protocol = indexes.EdgeNgramField(null=True)
def get_model(self):
return Post
def index_queryset(self, using=None):
return self.get_model().objects.date_sorted_list(public=False)
def prepare_date(self, obj):
if obj.post_type == "N":
return obj.public_date
elif obj.post_type == "E":
return obj.event_start.date()
elif obj.post_type == "F":
return obj.event_start.date()
def prepare_agenda(self, obj):
if obj.has_agenda:
return html2text(obj.agenda_html)
return None
def prepare_protocol(self, obj):
if obj.has_protocol:
return html2text(obj.protocol_html)
return None

View File

@@ -3,6 +3,7 @@ django-ckeditor==6.2.0
django-crontab==0.7.1
django-environ==0.8.1
django-filter==21.1
django-haystack==3.2.dev0
django-static-jquery-ui==1.12.1.1
django-softhyphen==1.1.0
django-taggit==2.1.0

View File

60
fet2020/search/forms.py Normal file
View File

@@ -0,0 +1,60 @@
from collections import deque
from haystack.forms import SearchForm
from haystack.query import SQ
from intern.models import Etherpad
from posts.models import Post
class FetUserSearchForm(SearchForm):
def search(self):
if not self.is_valid():
return self.no_query_found()
if not self.cleaned_data.get("q"):
return self.no_query_found()
sqs_post = self.searchqueryset.models(Post)
sqs_post = sqs_post.filter(
SQ(title__icontains=self.cleaned_data["q"])
| SQ(body__icontains=self.cleaned_data["q"])
| SQ(agenda__icontains=self.cleaned_data["q"])
| SQ(protocol__icontains=self.cleaned_data["q"])
)
sqs_intern = self.searchqueryset.models(Etherpad)
sqs_intern = sqs_intern.filter(etherpad__icontains=self.cleaned_data["q"])
results = deque([])
for elem in sqs_post.order_by("-date"):
results.append(elem.object)
for elem in sqs_intern.order_by("-date"):
results.append(elem.object)
return sorted(results, key=lambda elem: elem.date, reverse=True)
class NonUserSearchForm(SearchForm):
def search(self):
if not self.is_valid():
return self.no_query_found()
if not self.cleaned_data.get("q"):
return self.no_query_found()
sqs_post = self.searchqueryset.models(Post).filter(status="20")
sqs_post = sqs_post.filter(
SQ(title__icontains=self.cleaned_data["q"])
| SQ(body__icontains=self.cleaned_data["q"])
| SQ(agenda__icontains=self.cleaned_data["q"])
)
results = deque([])
for elem in sqs_post.order_by("-date"):
results.append(elem.object)
return sorted(results, key=lambda elem: elem.date, reverse=True)

7
fet2020/search/urls.py Normal file
View File

@@ -0,0 +1,7 @@
from django.urls import path, re_path
from . import views
urlpatterns = [
path("", views.index, name="index"),
]

26
fet2020/search/views.py Normal file
View File

@@ -0,0 +1,26 @@
from haystack.generic_views import SearchView
from haystack.query import SearchQuerySet
from django.contrib.auth.mixins import LoginRequiredMixin
from django.shortcuts import render
from .forms import FetUserSearchForm, NonUserSearchForm
class FetUserSearchView(LoginRequiredMixin, SearchView):
template_name = "search/index.html"
queryset = SearchQuerySet()
form_class = FetUserSearchForm
class NonUserSearchView(SearchView):
template_name = "search/index.html"
queryset = SearchQuerySet()
form_class = NonUserSearchForm
def index(request):
if request.user.is_authenticated:
return FetUserSearchView.as_view()(request)
return NonUserSearchView.as_view()(request)

View File

@@ -0,0 +1,33 @@
{% extends 'base.html' %}
{% block content %}
<main class="container mx-auto w-full px-4 my-8 flex-1">
<h1 class="page-title">Suchen</h1>
<div class="sm:flex sm:flex-row-reverse justify-center text-gray-700 dark:text-gray-200">
<form method="get" action=".">
<table>
{{ form.as_table }}
<tr>
<td>&nbsp;</td>
<td>
<input type="submit" value="Search">
</td>
</tr>
</table>
{% if object_list %}
<h3>Results</h3>
{% for result in object_list %}
<p>
<a href="{{ result.get_absolute_url }}">{{ result.date|date }}: {{ result.title }}</a>
</p>
{% empty %}
<p>No results found.</p>
{% endfor %}
{% endif %}
</form>
</div>
</main>
{% endblock %}

View File

@@ -0,0 +1,3 @@
{{ object.title }}
{{ object.date }}
{{ object.etherpad|safe }}

View File

@@ -0,0 +1,4 @@
{{ object.title }}
{{ object.body|safe }}
{{ object.agenda|safe }}
{{ object.protocol|safe }}