- 1. urls.py
- 2. views.py
- 3. Artikelmanager
- 4. suche/index.html
In früheren Artikeln haben wir uns angesehen, wie man eine Website-Suche auf einer Website durchführt. Nämlich:
- Seitensuche
- Erweiterte Suchoptionen
- Übergeben einer Liste von Argumenten an die Methode order_by zum Sortieren eines Abfragesatzes
Aber was ist, wenn Sie mehr als einen Inhaltstyp haben? Sie können Artikel, Kommentare, Foren und Forenbeiträge haben. Wie dann sein?
Wenn Sie alles selbst machen möchten, ohne Bibliotheken von Drittanbietern zu verwenden, müssen Sie alle erforderlichen Modelle durchsuchen und das Ergebnis zusammenführen. Genauso habe ich es auf der Website gemacht.
urls.py
Sie benötigen eine View-Klasse, die die Suchanforderung verarbeitet.
Der wichtige Punkt hier ist, dass wir Pull-Requests verarbeiten, damit Benutzer Links mit Suchergebnissen teilen können.
In die Datei urls.py schreiben wir die Route für die Suche
app_name = 'home' urlpatterns = [ path('search/', views.SearchView.as_view(), name='search'), ]
views.py
Nehmen wir an, wir haben mehrere Inhaltstypen:
- Artikel
- Kommentar
- Thema
- Post
Es ist notwendig, in der Ansicht nach allen Arten von Inhalten zu suchen und diese zu einem QuerySet zusammenzufassen und für die Paginierung und Auslieferung vorzubereiten
from itertools import chain from django.shortcuts import render from django.core.paginator import Paginator, PageNotAnInteger, EmptyPage from django.views import View from .models import Article, Comment, Topic, Post class ESearchView(View): template_name = 'search/index.html' def get(self, request, *args, **kwargs): context = {} q = request.GET.get('q') if q: query_sets = [] # Total QuerySet # Searching for all models query_sets.append(Article.objects.search(query=q)) query_sets.append(Comment.objects.search(query=q)) query_sets.append(Topic.objects.search(query=q)) query_sets.append(Post.objects.search(query=q)) # and combine results final_set = list(chain(*query_sets)) final_set.sort(key=lambda x: x.pub_date, reverse=True) # Sorting context['last_question'] = '?q=%s' % q current_page = Paginator(final_set, 10) page = request.GET.get('page') try: context['object_list'] = current_page.page(page) except PageNotAnInteger: context['object_list'] = current_page.page(1) except EmptyPage: context['object_list'] = current_page.page(current_page.num_pages) return render(request=request, template_name=self.template_name, context=context)
Die Nuance des obigen Codes besteht darin, dass wir alle Datenmodelle verketten und sie auch nach Datum sortieren. Um dies zu ermöglichen, werden wir die Funktionen der Programmiersprache Python verwenden, nämlich Ententypisierung. Die Sortierung nach Datum wird dadurch ermöglicht, dass alle Datenmodelle ein Veröffentlichungsdatumsfeld mit dem gleichen Namen pub_date haben.
Im Allgemeinen ist dies sehr wichtig, wenn Sie versuchen, Datenmodellfelder für verschiedene Datenmodelle gleich zu benennen. Dadurch können Sie bei der Entwicklung einer Django-Site sehr flexibel sein und Ententypisierung verwenden, um Vorlagen für die Anzeige von Daten zu schreiben, die nicht von einem bestimmten Datentyp abhängen, sondern von der Schnittstelle, die Ihre Datenmodelle unterstützen.
Interessant ist auch, dass die Objekte aller Datenmodelle, die in diesem Code dargestellt werden, dieselbe Lookup-Methode haben. Diese Methode ist nicht Standard. Um es zu implementieren, müssen Sie einen eigenen Modellmanager schreiben und ihn dem Bereich der Objekte zuweisen.
Artikelmanager
Stellen Sie sich einen typischen Artikelmanager vor. Wir erben es vom Basismodellmanager und definieren die Suchmethode mithilfe der Suchlogik. Ebenso müssen Sie diese Methode für alle Modelle registrieren, in denen die Suche durchgeführt wird.
from django.db import models from django.db.models import Q class ArticleManager(models.Manager): use_for_related_fields = True def search(self, query=None): qs = self.get_queryset() if query: or_lookup = (Q(title__icontains=query) | Q(content__icontains=query)) qs = qs.filter(or_lookup) return qs
Installieren eines Managers in einem Modell
class Article(models.Model): objects = ArticleManager()
suche/index.html
Und für die Suchvorlage können Sie eine leicht modifizierte Vorlage aus einem der ersten Artikel zur Organisation der Suche verwenden.
{% load bootstrap34%} {% block page %} <h1>Поиск</h1> {% if object_list %} {% for object in object_list %} <div> <a href="{{ object.get_absolute_url }}"> <h2>{{ object.itle }}</h2> </a> {{ object.content|safe }} <p><a class="btn btn-default btn-sm" href="{{ object.get_absolute_url }}">Читать далее</a></p> </div> {% endfor %} {% bootstrap_pagination object_list url=last_question %} {% else %} <p>Не найдено публикаций по вашему запросу<br>Попробуйте повторить запрос с другой формулировкой</p> {% endif %} {% endblock %}
Ich verwende in diesem Fall speziell den anonymisierten Objektparameter, der keinen Hinweis auf einen bestimmten Inhaltstyp enthält, sodass klar war, dass jedes Inhaltsobjekt vorhanden sein könnte. Die Hauptsache ist, dass alle Methoden für alle Modelle implementiert sind, die in dieser Vorlage verwendet werden.
Исправьте код в views.py, пропущен импорт chain из itertools.
Спасибо! Исправил.
Добрый день, небольшая проблемка с пагинацией, отображается информация только на первой странице при переходе на другую - пустая страница, views, models.Manager, шаблон, все сделал как в данном уроке, подставил только свои значения. Подскажите, в чем может быть проблема?
Спасибо.
Добрый день.
Покажите ваш код... Невозможно понять, где вы допустили ошибку, не видя, что вы делали.
Когда будете добавлять код в сообщение, используйте диалог вставки программного кода, одна из кнопок в тулбаре редактора комментариев. Тогда будет добавлена соответствующая разметка для блоков кода.
Опечатка в статье. Напишите так
И на старуху бывает проруха. Спасибо за вопрос.
Если бы не просмотрел ваш код, то скорее всего не заметил бы опечатку
Спасибо, Евгений, все заработало. Хороший сайт.
Спасибо за отзыв. Не стесняйтесь задавать вопросы. Только у меня убедительная просьба, все вопросы или на форуме сайта, или в комментариях к статьям. Чтобы потом у других пользователей было больше шансов найти ответ. Также на форуме присутствуют и другие опытные специалисты, они вполне могут тоже что-то подсказать, так что шансы получить ответ будут выше.
Здравствуйте, небольшой вопрос,
при добавлении формы пагинатора левая крайняя кнопка назад "<<" постоянно смещена вверх, относительно ряда цифр, не могу ее никак выровнять, в чем может быть проблема?
{% bootstrap_pagination object_list url=last_question %}
Хотел установить пагинатор прописав код, но немного запутался с адресами между страниц.
Подскажите, как правильно прописать адреса.
Спасибо.
У вас есть ещё какие-то кастомные стили, которые могут влиять на "<<", поскольку у меня такой проблемы не наблюдалось.
Ну по идее, это как-то тако должно выглядеть
Добрый день, Евгений,
сработал вот такой вариант:
href="?q={{ question }}&page={{ object_list.previous_page_number }}"
и во views добавил:
context['question'] = q
По поводу формы пагинатора, пробовал отключать все дополнительные стили, все также вылезает ошибка. Подумаю еще над этим, главное что есть рабочий вариант.
Спасибо за подсказку.