Рубрики
Без рубрики

Учебник поиска Django

В этом руководстве мы реализуем базовый поиск на веб-сайте Django и коснитесь способов улучшения его … Теги с Джанго, Питоном, Учебником, начинающими.

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

Примечание : Я дал версию этого учебника в Djangocon US 2019. Вы можете увидеть видео здесь:

Полный исходный код можно найти на Github Отказ

Чтобы начать давайте создадим новый проект Django ( Смотрите здесь, если вам нужна помощь с этим ). В вашей командной строке введите следующие команды, чтобы установить последнюю версию с Пипнв Создайте проект под названием CitySearch_Project Настройте начальную базу данных через мигрировать , а затем запустите локальный веб-сервер с помощью runserver. .

$ pipenv install django==3.0.3
$ pipenv shell
$ django-admin startproject citysearch_project .
$ python manage.py migrate
$ python manage.py runserver

Если вы перейдите к http://127.0.0.1:8000/ Вы увидите страницу приветствия Django, которая подтверждает, что все настроено правильно.

Города приложение

Теперь мы создадим одно приложение под названием Города Хранить список названий города. Мы ведем вещи намеренно базовыми. Остановите локальный сервер с Контроль + C и использовать StartApp Команда для создания этого нового приложения.

$ python manage.py startapp cities

Тогда обновите Stall_apps в нашей settings.py Файл, чтобы уведомить django о приложении.

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

Теперь для моделей. Мы назовем нашу одну модель Город И у него будет всего два поля: Имя и состояние . Поскольку администратор Django будет плюрализировать имя приложения для Город Мы также настроим 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

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

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

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

$ python manage.py createsuperuser

Теперь нам нужно обновить города/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 И войти в свою учетную запись Superuser.

Нажмите на Города Раздел и добавьте несколько записей. Вы можете увидеть мои четыре примера здесь.

Домашняя страница и результаты поиска

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

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

Во-первых, нам нужно добавить путь URL для нашего Города Приложение, которое можно сделать, импортируя включить и установить путь для него.

# 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 Файл в Города Приложение, однако Django не создает для нас с StartApp команда. Не заботятся, мы можем создать это сейчас из командной строки. Остановите сервер с Контроль + C Если он все еще работает.

$ touch cities/urls.py

В этом файле мы импортируем представления еще для каждого представления для каждого … 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'),
]

В-третьих, нам нужно настроить наши два взгляда. Домашняя страница будет просто шаблон, в конечном итоге, в поле поиска. Джанго 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'

В-четвертых и, наконец, нам нужны наши шаблоны. Мы могли бы добавить шаблоны в наших Города приложение Но я нахожу, что создание уровня проекта Шаблоны Папка вместо этого является более простым подходом.

Создать Шаблоны папка, а затем оба шаблоны home.html и search_results.html Отказ

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

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

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

Домашняя страница будет просто названием на этом этапе.


HomePage

Запустите веб-сервер снова с Python Manage.py Runserver И мы можем увидеть домашнюю страницу сейчас на http://127.0.0.1:8000/ Отказ

Теперь для страницы результатов поиска, которая будет пестроть object_list. Имя по умолчанию для объекта контекста ListView Возвращает. Тогда мы выводим оба имя и Государство для каждой записи.


Search Results

    {% for city in object_list %}
  • {{ city.name }}, {{ city.state }}
  • {% endfor %}

И … мы закончили. Наши результаты поиска доступны на http://127.0.0.1:8000/search/ Отказ

Формы и запросы

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

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

Основная фильтрация

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

Есть несколько способов настроить запрос и на самом деле можно сделать фильтрацию через Менеджер На самой модели, но … Чтобы сохранить вещи простыми, мы можем добавить фильтр только с одной строкой. Так что давайте сделаем это!

Вот это так, мы обновляем Queryset метод ListView и добавление жесткообразованного фильтра, так что только город с именем «Бостон» возвращается. В конце концов мы заменим это с помощью переменной, представляющей запрос поиска пользователей!

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

Обновите страницу результатов поиска, и вы увидите только «Бостон» теперь видны.

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

# cities/views.py
...
class SearchResultsView(ListView):
    model = City
    template_name = 'search_results.html'

    def get_queryset(self): # new
        return City.objects.filter(name__icontains='Boston')

Большую часть времени Встроенные методы запросов Фильтр () , все () , Получить () или Исключить () будет достаточно. Однако есть также очень надежный и подробный QuerySet API Доступно также.

Q объекты

Использование Фильтр () это мощно, и это даже возможно для Цепные фильтры вместе. Однако часто вы хотите более сложные поиски, такие как использование «или», когда пришло время обратиться к Q Объекты Отказ

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

# cities/views.py
from django.db.models import Q # new
...

class SearchResultsView(ListView):
    model = City
    template_name = 'search_results.html'

    def get_queryset(self): # new
        return City.objects.filter(
            Q(name__icontains='Boston') | Q(state__icontains='NY')
        )

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

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

Формы

Принципиально веб-форма проста: она принимает пользовательский ввод и отправляет его на URL через либо Получить или Пост метод. Однако на практике это фундаментальное поведение сети может быть чудовище сложным.

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

Есть только два варианта для «Как» отправляется форма: либо через Получить или Пост HTTP-методы.

А Пост Пакеты UP Form Data, кодируют его для передачи, отправляет ее на сервер, а затем получает ответ. Любой запрос, который изменяет состояние базы данных – создает, редактирует или удаляет данные – следует использовать Пост Отказ

А Получить Пучки образуют данные в строку, которая добавляется в URL назначения. Получить Следует использоваться только для запросов, которые не влияют на состояние приложения, например, поиск, где ничего в базе данных не меняется, мы просто делаем представление отфильтрованного списка в основном.

Если вы посмотрите на URL после посещения Google.com, вы увидите ваш поисковый запрос в фактической странице результатов поиска URL.

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

Форма поиска

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


HomePage

Для формы Действие Указывает, где перенаправить пользователя после подачи формы. Мы используем имя URL для наших результатов поиска здесь. Затем мы указываем использование Получить Как наше Метод Отказ

В нашем одном входе – можно иметь несколько входов или добавить кнопку здесь, если это необходимо – мы даем ему имя Q Что мы можем обратиться к позже. Укажите тип, который является текст Отказ А затем добавьте Зажигатель Значение, чтобы подсказать пользователя.

Это действительно это! На главной странице попробуйте ввести поиск, например, для «Сан-Диего».

После удаления возврата вы перенаправлены на страницу результатов поиска. Примечание, в частности, URL содержит наш поисковый запрос http://127.0.0.1:8000/search/?q=san+diego Отказ

Однако результаты не изменились! И это потому что наш Searchresultsview Все еще есть жесткодируемые значения от ранее. Последний шаг – взять поисковый запрос пользователя, представленный Q в URL и передайте его.

# cities/views.py
...
class SearchResultsView(ListView):
    model = City
    template_name = 'search_results.html'

    def get_queryset(self): # new
        query = self.request.GET.get('q')
        object_list = City.objects.filter(
            Q(name__icontains=query) | Q(state__icontains=query)
        )
        return object_list

Мы добавили Запрос переменная, которая принимает значение Q из представления формы. Затем обновите наш фильтр для использования Запрос как на название города и штате. Вот и все! Обновите страницу результатов поиска – она все еще имеет тот же URL с нашим запросом – и результат ожидается.

Если вы хотите сравнить свой код с официальным исходным кодом, его можно найти на Github Отказ

Следующие шаги

Наш базовый поиск сейчас завершен! Может быть, вы хотите добавить кнопку в форме поиска, которая может быть нажата в дополнение к возврату по ударам? Или, возможно, добавить некоторую проверку формы?

Помимо фильтрации с ANDS и OLS есть другие факторы, если мы хотим поиск качества Google, такие вещи, как актуальность и многое другое. Этот разговор Djangocon 2014: от __icontains для поиска Хороший вкус того, насколько глубоко может пойти поисковый кролик!

Оригинал: “https://dev.to/learndjango/django-search-tutorial-1gdm”