Django как сделать поиск по сайту
Перейти к содержимому

Django как сделать поиск по сайту

  • автор:

Django — Урок 034. Как сделать поиск по нескольким моделям данных

Но что, если у вас более одного типа контента. Вы можете иметь статьи, комментарии, форум и сообщения на форуме. Как тогда быть?

Если вы хотите сделать все сами, без использования сторонних библиотек, то вам нужно будет сделать поиск по всем нужным моделям и объединить результат. Я сделал точно так же на сайте.

urls.py

Вам понадобится один класс View, который будет обрабатывать поисковый запрос.

Важным моментом здесь является то, что мы будем обрабатывать запросы на получение, чтобы пользователи могли делиться ссылками с результатами поиска.

В файле urls.py пропишем маршрут для поиска

app_name = 'home' urlpatterns = [ path('search/', views.SearchView.as_view(), name='search'), ]

views.py

Допустим, у нас есть несколько типов контента:

Нужно в представлении выполнить поиск по всем видам контента и объединить их в один QuerySet и подготовить к пагинации и выдаче

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)

Нюанс приведенного выше кода в том, что мы объединяем все модели данных, а также сортируем их по дате. Чтобы это стало возможным, мы будем использовать возможности языка программирования Python, а именно утиную типизацию. Сортировка по дате стала возможной благодаря тому, что во всех моделях данных есть поле даты публикации с одинаковым названием pub_date.

В общем, это очень важно, когда вы пытаетесь назвать поля моделей данных одинаково для разных моделей данных. Это позволяет вам очень гибко разрабатывать сайт Django и использовать утиную типизацию для написания шаблонов для отображения данных, которые не зависят от конкретного типа данных, а скорее зависят от интерфейса, который поддерживает ваши модели данных.

Также интересно то, что объекты всех моделей данных, которые представлены в этом коде, имеют один и тот же метод поиска. Этот метод не является стандартным. Для его реализации нужно написать свой менеджер моделей и назначить его на поле объектов.

ArticleManager

Рассмотрим типовой менеджер статей. Мы наследуем его от базового менеджера моделей и определяем метод поиска с помощью логики поиска. Аналогично нужно прописать этот метод для всех моделей, в которых будет производиться поиск.

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

Установка менеджера в модель

class Article(models.Model): objects = ArticleManager()

search/index.html

А для шаблона поиска можно использовать немного измененный шаблон из одной из первых статей по организации поиска.

Поиск

>">

>

>

>">Читать далее

Не найдено публикаций по вашему запросу
Попробуйте повторить запрос с другой формулировкой

Я специально использую в данном случае параметр обезличенного объекта, который не имеет указания на конкретный тип контента, поэтому было понятно, что там может быть любой объект контента. Главное, чтобы все методы были реализованы для всех моделей, которые используются в этом шаблоне.

Рекомендуем хостинг TIMEWEB

Рекомендуем хостинг TIMEWEB

Стабильный хостинг, на котором располагается социальная сеть EVILEG. Для проектов на Django рекомендуем VDS хостинг.

Рекомендуемые статьи по этой тематике

  • Django - Урок 063. Полнотекстовый поиск на сайте для нескольких моделей с поддержкой мультиязычности
  • Django - Урок 033. Передача списка аргументов в метод order_by для сортировки QuerySet
  • Django - Урок 032. Расширенные параметры поиска
  • Django - Урок 012. Внедрение поиска по сайту с пагинацией результатов

По статье задано0 вопрос(ов)

Подписка на обсуждение 3
Подписка на раздел 176

Вам это нравится? Поделитесь в социальных сетях!

Руководство по созданию поиска на сайте в Django

Поиск на сайте в Django

В данном руководстве мы освоим базовый поиск по сайту Django и затронем способы улучшить его с более продвинутыми возможностями.

Полный исходный код можно найти на GitHub.

Для начала, давайте создадим новый проект Django (перейдите сюда, если нужна помощь). В вашей командной строке, введите следующие команды для установки последней версии при помощи Pipenv, создайте проект под названием citysearch_project , настройте внутреннюю базу данных через migrate и запустите локальный веб сервер при помощи runserver .

$ pipenv install django == 2.2.1
$ pipenv shell
$ django - admin startproject citysearch _ project .
$ python manage .py migrate
$ python manage .py runserver

Если вы перейдете на http://127.0.0.1:8000/ , вы увидите приветствие Django, которое подтверждает, что все настроено правильно. Локальный сервер не выражает все моменты реальной работы сайта на сервере, можете ознакомиться со списком хостингов https://hostinghub.ru/top/vds на которых вы можете запустить полноценный сайт на Python.

Django Search

Создаем приложение Cities в Django

Теперь мы создадим одно приложение под названием cities для хранения списка названий городов. Мы осознанно не будем выходить за рамки простых основ. Остановите локальный сервер при помощи Ctrl+C и используйте команду startapp для создания нашего нового приложения.

$ python manage .py startapp cities

Затем обновите INSTALLED_APPS внутри нашего файла settings.py , чтобы сообщить Django о новом приложении.

# citysearch_project/settings.py
INSTALLED_APPS = [
'cities.apps.CitiesConfig' , # new

Теперь перейдем к моделям. Мы назовем нашу единственную модель City . В ней будет два поля: name и state . Так как админка Django по умолчанию будет менять имя приложения во множественном числе на Citys , мы также настроим verbose_name_plural . И наконец настроим __str__ для отображения названия города.

# cities/models.py
from django . db import models
class City ( models . Model ) :
name = models . CharField ( max_length = 255 )
state = models . CharField ( max_length = 255 )
class Meta :
verbose_name_plural = "cities"
def __str__ ( self ) :
return self . name

Отлично, все настроено. Мы можем создать файл миграции для этого изменения, затем добавить его в нашу базу данных через migrate .

$ python manage . py makemigrations cities
$ python manage . py migrate

Есть несколько способов наполнить базу данных, но самый простой, на мой взгляд, это через admin. Создайте аккаунт суперпользователя, чтобы мы смогли зайти в админку.

$ python manage . py createsuperuser

Теперь нам нужно обновить cities/admin.py для отображения нашего приложения внутри админки.

# cities/admin.py
from django . contrib import admin
from . models import City
class CityAdmin ( admin . ModelAdmin ) :
list_display = ( "name" , "state" , )
admin . site . register ( City , CityAdmin )

Еще раз запустите сервер при помощи python manage.py runserver и направьтесь в админку по http://127.0.0.1:8000/admin , затем зайдите в свой аккаунт суперпользователя.

Django панель администратора

Нажмите на раздел cities и добавьте несколько записей. Здесь видно четыре моих примера.

Админка Django примеры

Домашняя страница и страница выдачи поиска Django

У нас есть заполненная база данных, однако все еще есть несколько шагов, которые нужно выполнить, перед тем как она может быть отображена на нашем сайте Django. В конце концов, нам нужна только домашняя страница и страница выдачи поиска. Каждой странице нужен надлежащий вид, url и шаблон. Порядок, в котором мы их будем создавать не принципиальный. Все должно быть на сайте для правильной работы.

В целом, я предпочитаю начинать с URL-ов, добавить views , и в конце создать шаблоны, чем мы и займемся.

Сначала нам нужно добавить путь URL для нашего приложения, это можно сделать, импортировав include и настроив путь к нему.

# citysearch_project/urls.py
from django . contrib import admin
from django . urls import path , include # new
urlpatterns = [
path ( 'admin/' , admin . site . urls ) ,
path ( '' , include ( 'cities.urls' ) ) , # new

Далее, нам нужнен файл urls.py внутри приложения cities , однако Django не создает такой для нас по команде startapp . Не нужно беспокоиться, мы можем создать его в командной строке. Останавливаем сервер при помощи Ctrl+C , если он еще работает.

$ touch cities / urls .py

Внутри этого файла мы импортируем еще не созданные представления ( views ) для каждой HomePageView и SearchResultsView , и указать путь к каждому из них. Обратите внимание на то, что мы указываем опциональное название URL для каждого из них.

Вот так это будет выглядеть:

# cities/urls.py
from django . urls import path
from . views import HomePageView , SearchResultsView
urlpatterns = [
path ( 'search/' , SearchResultsView . as_view ( ) , name = 'search_results' ) ,
path ( '' , HomePageView . as_view ( ) , name = 'home' ) ,

В третьих, нам нужно настроить наши два представления ( views ). Домашняя страница будет простым шаблоном с итоговой поисковой строкой. Для Django отлично подойдет TemplateView для этой цели. Страница поисковой выдачи упорядочит необходимые результаты, что хорошо ложится под ListView .

# cities/views.py
from django . views . generic import TemplateView , ListView
from . models import City
class HomePageView ( TemplateView ) :
template_name = 'home.html'
class SearchResultsView ( ListView ) :
model = City
template_name = 'search_results.html'

Последний шаг — наши шаблоны. Мы можем добавить шаблоны внутри нашего приложения cities , однако я нашел более простой подход, а именно — создание папку проектных шаблонов.

Создайте папку с шаблонами и затем оба шаблона: home.html и search_results.html .

$ mkdir templates
$ touch templates / home .html
$ touch templates / search_results .html

Обратите внимание на то, что нам также нужно обновить наш settings.py , чтобы указать Django на проектную папку с шаблонами. Это вы можете найти в разделе TEMPLATES .

# citysearch_project/settings.py
'DIRS' : [ os.path . join ( BASE_DIR , 'templates' ) ] , # new

Домашная страница выведет только заголовок.

HomePage

Запустите веб сервер еще раз при помощи python manage.py runserver . Теперь мы можем увидеть домашнюю страницу на http://127.0.0.1:8000/ .

Страница Django

Теперь, для страницы поисковой выдачи, которая будет выполнять цикл на object_list , вернется имя от контекстного объекта ListView . Затем мы выведем name и state для каждой записи из базы данных.

Search Results

Все готово! Наша страница поисковой выдачи доступна на http://127.0.0.1:8000/search/ .

Django результаты поиска

Формы и наборы запросов в Django

В конечном итоге базовая реализация поиска сводится к форме, которая передает пользовательский запрос — сам фактический поиск — и затем к набору запросов, который будет фильтровать результаты на основе этого запроса.

Мы можем начать с любого из них, но мы начнем с настройки фильтрации, после чего перейдем к форме.

Базовая фильтрация запросов в Django

В Django, QuerySet используется для фильтрации выдачи из модели базы данных. В данный момент, наша модель City выводит все свое содержимое. В итоге нам нужно ограничить страницу поисковой выдачи для фильтрации выведенных результатов, на основании поискового запроса от пользователя.

Есть несколько способов настроить набор запросов, и фактически возможно выполнить фильтрацию через менеджер самой модели, однако, чтобы сохранять простоту решений, мы можем добавить фильтр всего в одну строку. Давайте сделаем это.

Здесь мы обновляем метод queryset из ListView и добавляем фильтр, так что возвращается только город под названием Бостон . В итоге, мы заменим это переменной, которая представляет пользовательский поисковый запрос.

# cities/views.py
class SearchResultsView ( ListView ) :
model = City
template_name = 'search_results.html'
queryset = City . objects . filter ( name__icontains = 'Boston' ) # новый

Обновите страницу поисковой выдачи и вы увидите, что отображается только Бостон .

Django поисковая выдача

Также можно настроить queryset , переопределив метод get_queryset() , для изменения списка выданных городов. Явного преимущества в этом для нас нет, но этот подход мне кажется более гибким, чем просто указать атрибуты набора запросов.

# cities/views.py
class SearchResultsView ( ListView ) :
model = City
template_name = 'search_results.html'
def get_queryset ( self ) : # новый
return City . objects . filter ( name__icontains = 'Boston' )

Большую часть времени, встроенных методов filter() , all() , get() , или exclude() из QuerySet будет достаточно. Однако есть очень надежный и детализированный API QuerySet.

Объекты Q в Django

Использование filter() — эффективно, с ним даже можно связать фильтры вместе. Однако, вам могут понадобиться более сложные запросы, такие как ИЛИ (OR) . В таких случаях приходит время объектов Q.

Вот пример того, где мы настраиваем фильтр на поиск результата, который совпадает с названием города Бостон , или название штата, которое содержит аббревиатуру NY . Это также просто, как импорт Q вверху файла, и затем слегка поменять наш существующий запрос

# cities/views.py
from django . db . models import Q # новый
class SearchResultsView ( ListView ) :
model = City
template_name = 'search_results.html'
def get_queryset ( self ) : # новый
return City . objects . filter (
Q ( name__icontains = 'Boston' ) | Q ( state__icontains = 'NY' )

Обновите вашу страницу поисковой выдачи, чтобы увидеть результат.

Фильтрация Q в Django

Теперь, вернемся к нашей HTML-форме поиска для замены текущих прописанных значений переменными поискового запроса.

Формы для ввода данных на сайте в Django

По сути, веб формы — это просто: они берут ввод пользователя и направляют его в URL либо через метод GET , либо через POST . Однако на практике, это фундаментальное поведение веба может быть монструозно сложным.

Первая проблема — это отправка данных формы: куда на самом деле идут данные, и как мы их будет обрабатывать? Не говоря уже о множественных проблемах с безопасностью, когда вы разрешаете пользователям отправлять данные на веб-сайт.

Существует только два варианта того, как отправлять форму: либо через HTTP метод GET , либо через POST .

POST связывает данные формы, кодирует их для передачи, отправляет их на сервер и затем получает ответ. Любой запрос, который меняет состояние базы данных (создает, редактирует, или удаляет данные) — должен использовать POST .

GET связывает данные формы в строку, которая вносится в URL. GET должен быть использован для такого запроса, который не влияет на состояние приложения, например — поиск, где ничего внутри базы данных не меняется. Мы просто выполняем отфильтрованный просмотр списка.

Если вы взгляните на URL после поиска в гугле, вы увидите свой поисковый запрос в самом URL страницы результатов поиска ?q= .

Для дополнительной информации, Mozilla предоставляет подробные руководства как для отправки данных из формы, так и валидации форм данных, с которыми стоит ознакомиться, если вы не владеете основами.

Поисковая форма для сайта на Django

Впрочем, для наших целей, мы можем создать базовую форму поиска к существующей домашней странице уже сейчас. Вот так это выглядит. Мы рассмотрим каждую часть примера ниже.

Как создать базовый поиск для сайта Django?

Главная страница » Новости » Как создать базовый поиск для сайта Django?

11 апреля 2021

Как установить и подключиться к интерфейсу администратора Django

Конкретный контент любого сайта обычно извлекается пользователями через поиск Google, Yandex или другие поисковые системы. Однако, если этот вариант поиска реализован на веб-сайте, пользователи могут легко найти желаемый контент на сайте без использования поиска Google. Еще одно преимущество добавления опции поиска на веб-сайт заключается в том, что разработчик может правильно управлять результатами поиска. Это означает, что он может контролировать, какое содержимое сайта будет отображаться или нет. В этой статье будет показан процесс реализации базового поиска на сайте Django.

Предпосылки:

Перед тем, как практиковать сценарий этого руководства, вам необходимо выполнить следующие задачи:

  1. Установите Django версии 3+ на Ubuntu 20+ (желательно)
  2. Создайте проект Django
  3. Запустите сервер Django, чтобы проверить, работает ли сервер правильно или нет.

Настройте приложение Django:

Выполните следующую команду, чтобы создать приложение Django с именем searchchapp.

$ python3 manage.py startapp searchapp

Выполните следующую команду, чтобы создать пользователя для доступа к базе данных Django. Если вы создали пользователя раньше, вам не нужно запускать команду.

$ python3 manage.py createsuperuser

Добавьте имя приложения в часть INSTALLED_APP файла settings.py.

INSTALLED_APPS = [ ….. 'searchapp' ]

Создайте папку с именем templates внутри папки searchchapp и укажите местоположение шаблона приложения в части TEMPLATES файла settings.py.

TEMPLATES = [ < …. 'DIRS': ['/home/fahmida/django_pro/searchapp/templates'], …. >, ]

Создать модели:

Измените файл models.py с помощью следующего сценария. Здесь были определены два класса для создания двух реляционных таблиц с именами booktypes и books. Поле типа таблицы книг — это внешний ключ, который появится из таблицы типов книг.

models.py

# Импортировать необходимые модули from django.db import models from django.urls import reverse # Создать модель class Booktype(models.Model): btype = models.CharField(max_length=100, unique=True) class Meta: ordering=('btype',) # Создайте модель gor book class Book(models.Model): book_name = models.CharField(max_length=150) author_name = models.CharField(max_length=150) type = models.ForeignKey(Booktype, on_delete=models.CASCADE) price = models.FloatField() publication = models.CharField(max_length=100) class Meta: ordering=('book_name',) def __str__(self): return self.book_name def get_url(self): return reverse('book_detail', args=[self.id])

Создать шаблоны для поиска:

Для создания функции поиска, показанной в этой статье, вам потребуются три файла HTML. Это book_list.html, book_detail.html и search.html. Book_list.html отобразит все записи из таблицы books. Book_detail.html отобразит подробную информацию о конкретной книге. Search.html отобразит результат поиска после отправки формы поиска.

book_list.html

  Book List    

> Список книг

>">>

by >

$>

book_detail.html

    >   


>


Автор: >

Тип: >

Публикация: >

Цена: $>

search.html

Search Result

Found > result> >">

>

>

No results found.

Создание функций просмотра:

Измените файл views.py с помощью следующего сценария. В скрипте определены три функции. Функция book_list() отобразит файл book_list.html. Функция book_detail() отобразит файл book_detail.html. Функция search() будет искать записи на основе данных, отправленных формой поиска, и отображать результат в search.html.

views.py

# Импортировать необходимые модули from django.shortcuts import render,get_object_or_404 from .models import Book, Booktype from django.db.models import Q # Определите функцию для отображения всех книг def book_list(request): book = Book.objects.all() return render(request, 'book_list.html', ) # Определите функцию для отображения конкретной книги def book_detail(request,id): book = get_object_or_404(Book, id=id) types = Booktype.objects.all() t = types.get(id=book.type.id) return render(request, 'book_detail.html', ) # Определить функцию для поиска книги def search(request): results = [] if request.method == "GET": query = request.GET.get('search') if query == '': query = 'None' results = Book.objects.filter(Q(book_name__icontains=query) | Q(author_name__icontains=query) | Q(price__icontains=query) ) return render(request, 'search.html', )

Задайте пути для вызова функций просмотра:

Измените файл urls.py проекта Django с помощью следующего скрипта. В скрипте определены четыре пути. Путь admin/ используется для открытия административной панели Django. Пустой путь (») используется для вызова функции book_list (). Путь ‘/’ используется для вызова функции book_detail(). Путь search/ используется для вызова функции search().

urls.py

# Импортировать админ-модуль from django.contrib import admin # Импортировать модуль пути from django.urls import path # Импортировать представление from searchapp import views # Определить пути urlpatterns = [ path('admin/', admin.site.urls), path('', views.book_list, name='book_list'), path('/', views.book_detail, name='book_detail'), path('search/', views.search, name='search'), ]

Запустите приложение из браузера:

Выполните следующую команду, чтобы запустить сервер Django.

$ python3 manage.py runserver

Запустите следующий URL-адрес из любого браузера, чтобы отобразить список книг из таблицы.

Если пользователь щелкнет ссылку «PHP и MySQL для динамических веб-сайтов», подробности этой книги появятся в браузере.

Если пользователь ищет слово, физика в браузере, то в браузере отобразится следующий результат поиска.

Заключение:

Приложение Django с опцией базового поиска было реализовано в этой статье с использованием таблиц базы данных. Новые разработчики Django смогут реализовать функцию поиска на своем веб-сайте после прочтения этого руководства.

Создание представления поиска

Теперь мы создадим пользовательское представление, чтобы пользователи могли выполнять поиск по записям. Во-первых, нам нужна форма поиска. Измените файл forms.py приложения блога и добавьте следующую форму:

class SearchForm(forms.Form): query = forms.CharField() 

Мы будем использовать поле query, чтобы позволить пользователям вводить условия поиска. Измените файл views.py приложения блога и добавьте в него следующий код:

from .forms import EmailPostForm, CommentForm, SearchForm from haystack.query import SearchQuerySet def post_search(request): form = SearchForm() if 'query' in request.GET: form = SearchForm(request.GET) if form.is_valid(): cd = form.cleaned_data results = SearchQuerySet().models(Post).filter(content=cd['query']).load_all() # count total results total_results = results.count() return render(request, 'blog/post/search.html', 'form': form, 'cd': cd, 'results': results, 'total_results': total_results>) 

В этом представлении сначала мы создаем экземпляр SearchForm, который мы создали ранее. Мы собираемся отправить форму с помощью метода GET, чтобы результирующий URL-адрес включал параметр запроса. Чтобы узнать, была ли отправлена форма, мы рассмотрим query параметр в request.GET dictionary. Когда форма отправляется, мы создаем ее экземпляр с отправленными данными GET и проверяем допустимые данные. Если форма валидна, мы используем SearchQuerySet для выполнения поиска индексированных объектов Post, основное содержимое которых содержит заданный запрос. Метод load_all загружает все связанные объекты Post из базы данных одновременно. Этот метод позволяет заполнить результаты поиска объектами базы данных, чтобы избежать доступа к базе данных для каждого объекта при итерации результатов для доступа к данным объекта. Наконец, мы храним общее число результатов в переменной total_results и передаем локальные переменные в качестве контекста для визуализации шаблона.

Представление поиска готово. Необходимо создать шаблон для отображения формы и результатов поиска, когда пользователь выполняет поиск. Создайте новый файл в каталоге templates/blog/post/, назовите его search.html и добавьте в него следующий код:

Search

Posts containing ">"

Found > result>

>">>

>

There are no results for your query.

">Search again

Search for posts

>

Как и в представлении поиска, мы узнаем, если форма была отправлена на основании наличия параметра query. Перед отправкой post мы выводим форму и кнопку отправки. После отправки post мы выводите выполненный query, общее число результатов и список результатов. Каждый result — это документ, возвращенный Solr и инкапсулированный в Haystack. Нам нужно использовать result.object для доступа к фактическому объекту Post, связанному с этим результатом.

Наконец, измените файл urls.py приложения блога и добавьте следующий шаблон URL-адреса:

url(r'^search/$', views.post_search, name='post_search'), 

Откройте в браузере http://127.0.0.1:8000/blog/search/ . Вы должны видеть такую форму поиска:

Теперь введите запрос и нажмите кнопку Search. Результаты поиска будут выглядеть следующим образом:

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *