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

Создание продуктов данных с помощью Python: Веб-сайт обзора вин с использованием Django и Bootstrap

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

Автор оригинала: Jose A Dianes.

Вступление

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

Мы хотим, чтобы этот учебник оставил вам продукт, который вы можете адаптировать и показать в своем портфолио. С этой целью мы объясним, как настроить виртуальную машину Koding и использовать ее в качестве сервера разработки Django и Pandas + Scikit-learn Python.

Затем мы запустим проект Django и приложение Django для нашего веб-приложения Wine recommender. Это будет постепенный процесс, за которым может последовать проверка отдельных тегов в нашем репо GitHub . Таким образом, вы можете работать над теми отдельными задачами на данном этапе, которые вам кажутся более интересными или трудными.

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

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

Помните, что вы можете следовать учебнику на любом этапе разработки, разветвляя репо в свою учетную запись GitHub, а затем клонируя в свою рабочую область и проверяя соответствующий тег. Разветвляя репо, вы можете изменять его по своему усмотрению и экспериментировать с ним столько, сколько вам нужно. Если в какой-то момент вам захочется немного помочь с каким-то шагом урока или сделать его своим собственным, мы можем провести сеанс 1:1 Codementor об этом.

Обычно будет развернута последняя стадия приложения, запущенного в кодинге , включая все связанные обновления учебников. Но давайте начнем наш проект с нуля!

Кодирование как сервер разработки

Koding -это облачная среда разработки в комплекте с бесплатными виртуальными машинами (VMS), привлекательной ИДЕЕЙ и доступом к терминалу уровня sudo. Его можно использовать в качестве площадки для разработки программного обеспечения и всего, что вам нужно для переноса разработки программного обеспечения в облако! Виртуальная машина Кодинга имеет множество популярных программных пакетов и языков программирования, предварительно установленных, так что вы можете сосредоточиться на обучении, а не на установке и настройке.

Мы использовали кодирование во время работы в этом учебнике, поэтому это хороший вариант, если вы хотите следовать ему. У нас даже есть последняя версия веб-сайта, развернутая на тестовом сервере, работающем в нашей виртуальной машине Koding (можно найти здесь ). Однако это не является обязательным требованием, и вы можете работать над учебником на своей собственной машине или любой другой системе, которая может установить Python и необходимые нам пакеты. Об этом мы рекомендуем установить Anaconda , которая поставляется со всеми аналитическими пакетами, которые нам понадобятся на более поздних этапах разработки продукта.

Поэтому, если вы хотите следовать нашим же шагам, первое, что нужно сделать, это зарегистрироваться на Кодинг . Единственная проблема с бесплатной учетной записью заключается в том, что она поставляется с 3 ГБ дискового пространства, а нам нужно не менее 4 ГБ. Вам нужно будет пригласить пару друзей, используя вашу реферальную ссылку, чтобы вы могли получить больше места.

Как только ваша виртуальная машина Koding будет запущена и запущена, перейдите на веб-сайт Anaconda и загрузите+установите версию Anaconda для вашей ОС .

Как только это будет сделано, последний бит-установить Django. Что я сделал, так это установил его, используя версию pip , которая поставляется с Anaconda. То есть, если вы находитесь в корневой папке, в которой находится ваша установка Anaconda, просто введите.

./anaconda/bin/pip install django

Репо GitHub

Одна из самых крутых вещей в этом учебнике заключается в том , что весь код доступен на GitHub , и что каждый раздел помечен другим тегом (например, stage-0 – это пустое репо). Поэтому перейдите в репо и разветвите его на свою учетную запись GitHub, а затем клонируйте его на свой сервер разработки (кодирование в нашем случае).

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

git checkout stage-0.1

Ядро нашего веб-приложения Django

Жизненный цикл проекта Django управляется двумя командами. Сначала мы используем django-admin.py для создания проекта. Затем мы используем python manage.py КОМАНДА , чтобы сделать что-нибудь еще. Итак, давайте начнем с создания проекта Django.

Запуск проекта с помощью start project

Создайте папку каталога, в которую вы хотите поместить свой проект Django, и переместите ее с помощью cd . Затем запустите django-admin.py команда для создания проекта выглядит следующим образом.

django-admin.py startproject winerama

Давайте посмотрим на то, что мы только что создали, выполнив команду start project .

tree winerama  

winerama
|-- manage.py
`-- winerama
    |-- __init__.py
    |-- settings.py
    |-- urls.py
    `-- wsgi.py

Это требует небольшого объяснения:

  • Корневой каталог cinerama/ является контейнером для нашего проекта.
  • manage.py – это утилита командной строки, которая позволяет нам взаимодействовать с нашим проектом различными способами. Мы будем использовать его все время, так что его цель будет ясна через минуту.
  • Внутренний каталог cinerama/ – это фактический пакет Python для нашего проекта. Его имя также является именем пакета Python для файлов проекта.
  • mysite/__init__.py – это пустой файл, который сообщает Python, что этот каталог следует считать пакетом Python.
  • mysite/settings.py – это файл настроек/конфигурации для вашего проекта.
  • mysite/urls.py содержит объявления URL-адресов для этого проекта Django.
  • mysite/wsgi.py -это точка входа для веб-серверов, совместимых с WSGI, для обслуживания нашего проекта.

Запуск сервера с помощью runserver

python manage.py runserver 0.0.0.0:8000

Затем мы можем перейти на ваш общедоступный URL-адрес сервера кодинга http://KODING_USERNAME.koding.io:8000 где мы заменяем KODING_USERNAME на нашего пользователя Koding и проверяем, как выглядит веб-сайт до сих пор.

введите описание изображения здесь

Настройка базы данных

А теперь открывай winerama/settings.py . Это обычный модуль Python с переменными уровня модуля, представляющими настройки Django.

По умолчанию Django использует SQLite, и мы будем придерживаться его. SQLite включен в Python, поэтому вам не нужно будет устанавливать что-либо еще для поддержки вашей базы данных. Если вы планируете развернуть этот проект в рабочей среде, вам лучше перейти к какой-нибудь готовой к работе базе данных, такой как PostgreSQL, чтобы избежать головной боли при переключении баз данных в будущем.

Поэтому нам не нужно ничего менять в вашем файле настроек. Если таковые имеются, измените winerama/settings.py чтобы установить TIME_ZONE в свой часовой пояс.

Но в любом случае некоторые из установленных приложений (подробнее об этом позже) используют по крайней мере одну таблицу базы данных, поэтому нам нужно создать таблицы в базе данных, прежде чем мы сможем их использовать. Для этого выполните следующую команду:

python manage.py migrate

Приложения против проектов

Теперь мы готовы запустить наше приложение для обзоров вин. Но подождите, в чем разница между приложением и проектом? С сайта Django:

В чем разница между проектом и приложением? Приложение – это веб-приложение, которое что-то делает, например, система блогов, база данных общедоступных записей или простое приложение для опроса. Проект-это набор конфигураций и приложений для конкретного веб-сайта. Проект может содержать несколько приложений. Приложение может быть в нескольких проектах. […] Приложения Django” подключаемы”: вы можете использовать приложение в нескольких проектах и распространять приложения, потому что они не должны быть привязаны к данной установке Django.

Таким образом, в нашем случае наш проект Winerama будет содержать наше первое отзывы приложение, которое позволит пользователям добавлять отзывы о винах. Для этого из корневой папки wintertime , где manage.py is, нам нужно использовать команду startapp следующим образом.

python manage.py startapp reviews

Это создаст следующую структуру папок.

tree reviews

reviews
|-- __init__.py
|-- admin.py
|-- migrations
|   `-- __init__.py
|-- models.py
|-- tests.py
`-- views.py

Мы познакомимся с этими файлами в следующих разделах при создании сущностей модели, представлений и настройке интерфейса администратора.

Но сначала нам нужно активировать наше приложение для отзывов. Отредактируйте winerama/settings.py файл и измените параметр INSTALLED_APPS , чтобы включить сильные “отзывы” следующим образом.

INSTALLED_APPS = (
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'reviews',
)

Добавление объектов модели

На этом первом этапе наше приложение wine reviews будет содержать две типовые сущности: Wine и Review. У Вина есть только название. Обзор содержит четыре поля: имя пользователя, сделавшего обзор, рейтинг вина, дату публикации и текстовый обзор. Кроме того, каждый отзыв связан с вином.

Эти две сущности представлены классами Python, которые мы добавляем в reviews/models.py файл выглядит следующим образом.

from django.db import models
import numpy as np


class Wine(models.Model):
    name = models.CharField(max_length=200)
    
    def average_rating(self):
        all_ratings = map(lambda x: x.rating, self.review_set.all())
        return np.mean(all_ratings)
        
    def __unicode__(self):
        return self.name


class Review(models.Model):
    RATING_CHOICES = (
        (1, '1'),
        (2, '2'),
        (3, '3'),
        (4, '4'),
        (5, '5'),
    )
    wine = models.ForeignKey(Wine)
    pub_date = models.DateTimeField('date published')
    user_name = models.CharField(max_length=100)
    comment = models.CharField(max_length=200)
    rating = models.IntegerField(choices=RATING_CHOICES)

Каждая из наших двух сущностей модели представлена классом, который подклассы django.db.models.Модель . Каждая переменная класса модели представляет поле базы данных в модели и представлена экземпляром подкласса полей. Это указывает, какой тип данных содержит каждое поле. Имя поля-это ссылка на его код в удобном для машины формате, и наша база данных будет использовать его в качестве имени столбца.

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

Некоторые классы полей имеют обязательные и необязательные аргументы, такие как max_length для CharField и т. Д. Это используется как в схеме базы данных, так и при проверке.

Наконец, мы указываем отношения между сущностями с помощью поля ForeignKey . Это говорит Джанго, что каждый Обзор связан с одним вином .

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

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

python manage.py makemigrations reviews

И теперь мы можем применить наши миграции к базе данных следующим образом, без потери данных.

python manage.py migrate

Эта точка проекта соответствует тегу git stage-0.1 .

Предоставление сайта администратора

Прежде всего, нам нужно создать пользователя-администратора, выполнив следующую команду для корневой папки shinerama/ , которая содержит manage.py .

python manage.py createsuperuser

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

Сайт администратора активирован по умолчанию. Давайте исследуем его. Если ваш веб – сайт не запущен и не работает, используйте следующую команду.

python manage.py runserver 0.0.0.0:8000

И теперь вы можете перейти к http://KODING_USERNAME:8000/admin/ (не забудьте заменить ИМЯ пользователя KODING_USERNAME на ваше фактическое имя пользователя Koding) и войдите в систему с помощью пользователя и пароля, которые вы указали ранее.

Вы заметите, что наши объекты модели не могут быть изменены на сайте администратора. Для того, чтобы они были там, нам нужно добавить их в reviews/admin.py файл, так что это выглядит следующим образом.

from django.contrib import admin

from .models import Wine, Review

class ReviewAdmin(admin.ModelAdmin):
    model = Review
    list_display = ('wine', 'rating', 'user_name', 'comment', 'pub_date')
    list_filter = ['pub_date', 'user_name']
    search_fields = ['comment']
    
admin.site.register(Wine)
admin.site.register(Review, ReviewAdmin)

Мы в основном импортируем классы моделей, которые мы только что определили, а затем используем register() в Django, который мы хотим, чтобы вина и обзоры были доступны на сайте администратора.

введите описание изображения здесь

Если мы снова перейдем на сайт администратора, мы увидим новый раздел Отзывы с элементами Вина и Отзывы внутри. Эти элементы включают в себя две кнопки действий: Добавить и Изменить . Добавить можно использовать для представления новых вин или обзоров вин. Формы автоматически генерируются из моделей Wine и Review .

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

  • какие столбцы (и в каком порядке) мы хотим отобразить в списке записей. То есть при использовании кнопки Change или при переходе к admin/reviews/wine или admin/reviews/review мы увидим список всех добавленных записей. То, как отображаются записи, когда мы переходим в раздел отзывов, определяется полем list_display в классе Review Admin .
  • Список фильтров, которые можно использовать для просмотра отзывов.
  • Список полей, которые будут сопоставлены при использовании поля поиска.

Мы предлагаем вам поэкспериментировать с этим классом Review Admin (или создать свой собственный Wine Admin ), пока вы не будете довольны результатами.

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

Этот этап проекта соответствует тегу git stage-0.2 .

Добавление веб-представлений

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

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

Но давайте покажем это на практике.

Первое, что нам нужно сделать, это включить наше приложение отзывов в URL-адреса проекта. Для этого отредактируйте winerama/urls.py файл (обратите внимание на файл отзывов, пока) и измените шаблон url списка, чтобы он выглядел следующим образом.

urlpatterns = [
    url(r'^reviews/', include('reviews.urls', namespace="reviews")),
    url(r'^admin/', include(admin.site.urls)),
]

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

Сопоставления могут извлекать части URL-адреса и передавать его в качестве параметра в представление обработки. Например, отображение:

url(r'^review/(?P[0-9]+)/$', views.review_detail, name='review_detail')  

извлекает число после части reviews/review/ и передает его в функцию review_detail , определенную позже.

Поэтому для того, чтобы это сопоставление работало, нам нужно добавить его в наш reviews/urls.py файл. Давайте добавим некоторые из них. Изменить reviews/urls.py файл должен выглядеть следующим образом.

from django.conf.urls import url
from . import views

urlpatterns = [
    # ex: /
    url(r'^$', views.review_list, name='review_list'),
    # ex: /review/5/
    url(r'^review/(?P[0-9]+)/$', views.review_detail, name='review_detail'),
    # ex: /wine/
    url(r'^wine$', views.wine_list, name='wine_list'),
    # ex: /wine/5/
    url(r'^wine/(?P[0-9]+)/$', views.wine_detail, name='wine_detail'),
]

Структура отображения такая же, как и раньше. Например, мы указываем, что любой запрос, начинающийся с пустой строки (плюс префикс reviews/ , который мы добавили на уровне проекта), будет обрабатываться функцией с именем review_list , определенной в нашем reviews/views.py файл, и на него будут ссылаться в локальном пространстве имен (помните, что мы дали пространство имен отзывы в проекте winerama/urls.py ) с именем reviews_list .

Итак, теперь нам нужны реальные виды. Как мы уже говорили, это всего лишь функции Python, которые имеют дело с сущностями модели и решают, как отображать результаты (в нашем случае это HTML-страница). Изменить reviews/views.py файл должен выглядеть следующим образом.

from django.shortcuts import get_object_or_404, render

from .models import Review, Wine


def review_list(request):
    latest_review_list = Review.objects.order_by('-pub_date')[:9]
    context = {'latest_review_list':latest_review_list}
    return render(request, 'reviews/review_list.html', context)


def review_detail(request, review_id):
    review = get_object_or_404(Review, pk=review_id)
    return render(request, 'reviews/review_detail.html', {'review': review})


def wine_list(request):
    wine_list = Wine.objects.order_by('-name')
    context = {'wine_list':wine_list}
    return render(request, 'reviews/wine_list.html', context)


def wine_detail(request, wine_id):
    wine = get_object_or_404(Wine, pk=wine_id)
    return render(request, 'reviews/wine_detail.html', {'wine': wine})

Там мы определили четыре различных представления для каждого из четырех различных сопоставлений URL-адресов, которые мы указали ранее. Каждая функция получает по крайней мере параметр request object и, возможно, дополнительные параметры, указанные в сопоставлении URL-адресов. Например, функция review_detail также получает параметр review_id , как мы указали в сопоставлении.

Как только мы оказываемся внутри функции представления, мы обычно выполняем некоторый запрос модели и создаем объект контекста с результатами. Запросы обычно выполняются с использованием атрибута .objects в данном классе сущностей домена (например, Review.objects ). Мы можем применять различные методы сортировки, фильтры и т.д., Пока не получим желаемые результаты (посмотрите здесь подробнее о наборах запросов). Этот объект контекста затем передается функции render вместе со ссылкой на файл шаблона, который создаст результирующую веб-страницу.

В том порядке, в котором они отображаются в файле, представления:

  • review_list : получает список из последних 9 отзывов и отображает его с помощью `reviews/list.html”.
  • review_detail : получает отзыв с учетом его идентификатора и отображает его с помощью review_detail.html .
  • wine_list : получает все вина, отсортированные по имени, и передает их в wine_list.html для визуализации.
  • wine_detail : получает вино из БД с учетом его идентификатора и отображает его с помощью wine_detail.html .

А теперь нам нужно создать HTML-шаблоны, которые будут генерировать конечные страницы. Они выражены на языке шаблонов Django. Этот язык позволяет нам помещать переменные заполнители и структуры управления в HTML-код, чтобы динамически генерировать конечную веб-страницу.

введите описание изображения здесь

Например, так выглядит шаблон review_list view.

Latest reviews

{% if latest_review_list %}
{% for review in latest_review_list %}

{{ review.wine.name }}

rated {{ review.rating }} of 5 by {{ review.user_name }}

{{ review.comment }}

{% endfor %}
{% else %}

No reviews are available.

{% endif %}

Этот шаблон использует некоторые структуры языка шаблонов Django. Все они заключены в {% ... %} элементы. Например, директива {% if latest_review_list %}{% else %}{% endif %} похожа на любую другую структуру if-else в компьютерном программировании. Первый раздел будет выполняться, если объект latest_review_list существует, а второй раздел будет действовать иначе. Объект latest_review_list является частью объекта контекста, который мы создаем и передаем в render в функции представления, определенной в reviews/views.py . Блок for эквивалентен программированию для и так далее. Доступ к методам и полям объектов осуществляется с помощью точечной нотации.

Django также предоставляет нам URL-адрес { % ... %} мы можем использовать вместе с пространствами имен, чтобы не жестко кодировать URL-адреса в шаблонах. Мы используем это в нашем шаблоне, как видим.

Вы можете проверить, как выглядят все представления в stage-0.3 репо проекта. Мы не собираемся объяснять здесь все детали языка шаблонов Django. Для любопытного читателя взгляните на официальную документацию Django .

Поэтому добавление новых сопоставлений так же просто, как добавление дополнительных элементов в представление url-адреса . Как только мы это сделаем, нам нужно добавить соответствующую функцию в reviews/views.py и создайте HTML-страницу, которая будет отображать результаты.

Мы добавили пару вин и отзывов в базу данных, так что вы можете перейти по ссылке http://KODING_USERNAME:8000/reviews/ и увидеть это в действии. Это одна из четырех возможных веб-страниц, которые мы можем посетить в нашем приложении. Можете ли вы проверить все из них с помощью своего браузера из того, что мы видели в reviews/urls.py ? Попробуйте построить URL-адреса.

Эта точка проекта соответствует тегу git stage-0.3 .

Добавление Отзывов С Помощью Форм

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

введите описание изображения здесь

Этот вид является подробным видом вина. Помните, что, когда мы показываем детали вина, мы также показываем некоторые из его недавних обзоров. Что мы хотим сделать, так это предоставить также HTML-форму, которую можно использовать для добавления нового обзора для этого конкретного вина.

Давайте начнем с самого простого. Вот как выглядит представление сведений о вине, включая форму.

{{ wine.name }}

{{ wine.review_set.count }} reviews ({{ wine.average_rating | floatformat }} average rating)

Recent reviews

{% if wine.review_set.all %}
{% for review in wine.review_set.all %}
{{ review.comment }}
Rated {{ review.rating }} of 5 by {{ review.user_name }}
Read more
{% endfor %}
{% else %}

No reviews for this wine yet

{% endif %}

Add your review

{% if error_message %}

{{ error_message }}

{% endif %}
{% csrf_token %} {{ form.as_p }}

Вы можете видеть, что на самом деле мы не включили туда никаких полей формы. То, что мы здесь делаем, – это использование языка шаблонов Django, чтобы оставить объект {{ form.as_p }} для визуализации с соответствующими полями (как HTML-элементы). Мы определяем этот класс формы как Модель формы в файле reviews/forms.py следующим образом.

from django.forms import ModelForm, Textarea
from reviews.models import Review

class ReviewForm(ModelForm):
    class Meta:
        model = Review
        fields = ['user_name', 'rating', 'comment']
        widgets = {
            'comment': Textarea(attrs={'cols': 40, 'rows': 15})
        }

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

При первом отображении сведений о вине нам нужно передать новый пустой объект формы. Мы добавим это в нашу функцию wine_detail view. Мы также добавляем представление функции add_review в reviews/views.py . Файл будет выглядеть следующим образом.

from django.shortcuts import get_object_or_404, render
from django.http import HttpResponseRedirect
from django.core.urlresolvers import reverse
from .models import Review, Wine
from .forms import ReviewForm
import datetime


def review_list(request):
    latest_review_list = Review.objects.order_by('-pub_date')[:9]
    context = {'latest_review_list':latest_review_list}
    return render(request, 'reviews/review_list.html', context)


def review_detail(request, review_id):
    review = get_object_or_404(Review, pk=review_id)
    return render(request, 'reviews/review_detail.html', {'review': review})


def wine_list(request):
    wine_list = Wine.objects.order_by('-name')
    context = {'wine_list':wine_list}
    return render(request, 'reviews/wine_list.html', context)


def wine_detail(request, wine_id):
    wine = get_object_or_404(Wine, pk=wine_id)
    form = ReviewForm()
    return render(request, 'reviews/wine_detail.html', {'wine': wine, 'form': form})


def add_review(request, wine_id):
    wine = get_object_or_404(Wine, pk=wine_id)
    form = ReviewForm(request.POST)
    if form.is_valid():
        rating = form.cleaned_data['rating']
        comment = form.cleaned_data['comment']
        user_name = form.cleaned_data['user_name']
        review = Review()
        review.wine = wine
        review.user_name = user_name
        review.rating = rating
        review.comment = comment
        review.pub_date = datetime.datetime.now()
        review.save()
        # Always return an HttpResponseRedirect after successfully dealing
        # with POST data. This prevents data from being posted twice if a
        # user hits the Back button.
        return HttpResponseRedirect(reverse('reviews:wine_detail', args=(wine.id,)))

    return render(request, 'reviews/wine_detail.html', {'wine': wine, 'form': form})

Функция add_review отвечает за проверку формы и создание нового экземпляра проверки. Первое, что он делает, – это использует URL-адрес запроса wine ID для поиска вина, к которому мы собираемся добавить отзыв. Он перенаправит представление на страницу 404, если не найдет ее. В противном случае он создаст Форму обзора экземпляр из данных записи запроса).

Мы можем проверить форму с помощью одного вызова form.isvalid() . Когда for недействителен, мы просто снова отобразим страницу сведений о вине, передав исходную форму, чтобы ее можно было исправить. Если форма действительно действительна, мы создаем объект обзора, сохраняем его и снова перенаправляем на страницу сведений о вине. Здесь мы не визуализируем непосредственно страницу, а внутренне переходим к представлению wine_detail с соответствующим идентификатором wine.

Теперь нам нужно соединить все вместе. Атрибут action в элементе form HTML указывает, какой URL-адрес обрабатывает запрос post после отправки формы. Затем нам нужно создать соответствующее сопоставление URL-адресов в reviews/urls.py . Измените этот файл, который должен выглядеть следующим образом.

from django.conf.urls import url

from . import views

urlpatterns = [
    # ex: /
    url(r'^$', views.review_list, name='review_list'),
    # ex: /review/5/
    url(r'^review/(?P[0-9]+)/$', views.review_detail, name='review_detail'),
    # ex: /wine/
    url(r'^wine$', views.wine_list, name='wine_list'),
    # ex: /wine/5/
    url(r'^wine/(?P[0-9]+)/$', views.wine_detail, name='wine_detail'),
    url(r'^wine/(?P[0-9]+)/add_review/$', views.add_review, name='add_review'),
]

С помощью этого мы можем перейти на любую страницу сведений о вине (например, http://KODIG_USERNAME:8000/reviews/wine/1/) и добавить новый отзыв. Не беспокойтесь слишком сильно о том, что страница не очень привлекательна. Мы решим эту проблему в следующих двух разделах.

введите описание изображения здесь

Эта точка проекта соответствует тегу git stage-0.4 .

Повторное использование шаблона

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

Одним из вариантов было бы скопировать список ссылок на каждой странице, которая у нас есть (до сих пор их было четыре). Но мы знаем, что это не очень хорошая практика. К счастью, язык шаблонов Django позволяет нам расширять шаблоны. Благодаря этому мы можем определить базовый шаблон, содержащий меню и структуру главной страницы, а затем заставить каждое из наших четырех представлений расширить этот базовый шаблон.

Вот как reviews/templates/reviews/base.html шаблон будет выглядеть следующим образом.

введите описание изображения здесь

{% block title %}(no title){% endblock %}

{% block content %}(no content){% endblock %}

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

Два других раздела определяют структуру для всех наших представлений. Они состоят из блока заголовка и блока содержимого. Мы используем язык шаблонов Django {% block ... %} директива для этой цели.

Затем мы должны сделать каждый из HTML-шаблонов, которые мы создаем для наших представлений, чтобы расширить этот базовый шаблон. Например, review_list.html шаблон будет выглядеть следующим образом.

{% extends 'reviews/base.html' %}

{% block title %}

Latest reviews

{% endblock %} {% block content %} {% if latest_review_list %}
{% for review in latest_review_list %}

{{ review.wine.name }}

rated {{ review.rating }} of 5 by {{ review.user_name }}

{{ review.comment }}

{% endfor %}
{% else %}

No reviews are available.

{% endif %} {% endblock %}

Первая строка всегда является {% extends 'reviews/base.html' %} директива, указывающая, что наш шаблон расширяет базовый шаблон. Делая это, наш review_list.html автоматически включит навигационное меню. Затем мы определяем содержимое двух блоков, которые мы определили в базовом шаблоне. Django заменит базовые блоки на те, которые мы определяем здесь.

Проверьте остальные представления в репо учебника. Эта точка проекта соответствует тегу git stage-0.5 .

Стайлинг с Bootstrap

Bootstrap – это популярный фреймворк HTML, CSS и JS для разработки адаптивных мобильных проектов в Интернете. Наши веб-страницы выглядят довольно скучно и визуально неорганизованно. Мы будем использовать Bootstrap, чтобы сделать их более удобными для пользователей.

Самый простой (и самый чистый) способ использовать Bootstrap для проекта Django-это установить и использовать приложение Bootstrap 3 для Django . Установка так же проста, как перейти к нашему терминалу кодирования и выполнить с помощью команды Anaconda pip следующее:

pip install django-bootstrap3

Как только мы это сделаем, мы можем изменить настройки проекта Winerama, чтобы включить Bootstrap 3 для приложений Django, определив список INSTALLED_APPS следующим образом.

INSTALLED_APPS = (
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'bootstrap3',
    'reviews',
)

Теперь мы можем использовать Bootstrap в наших шаблонах. Сначала мы добавим его в наш base.html шаблон, чтобы оставить его следующим образом.

{% load bootstrap3 %}

{% bootstrap_css %}
{% bootstrap_javascript %}

{% block bootstrap3_content %}

{% block title %}(no title){% endblock %}

{% bootstrap_messages %} {% block content %}(no content){% endblock %}
{% endblock %}

Мы изменили файл базового шаблона в соответствии с Bootstrap 3 для документации Django . В основном мы импортируем некоторые библиотеки, а затем назначаем некоторые классы различным элементам HTML. Здесь нет ничего особенного.

Остальные шаблоны имеют незначительные изменения. Мы просто добавляем некоторые классы начальной загрузки, где это необходимо. Единственный, который имеет серьезные изменения, – это wine_detail.html шаблон. Это будет выглядеть следующим образом:

{% extends 'reviews/base.html' %}
{% load bootstrap3 %}

{% block title %}

{{ wine.name }}

{{ wine.review_set.count }} reviews ({{ wine.average_rating | floatformat }} average rating)
{% endblock %} {% block content %}

Recent reviews

{% if wine.review_set.all %}
{% for review in wine.review_set.all %}
{{ review.comment }}
Rated {{ review.rating }} of 5 by {{ review.user_name }}
Read more
{% endfor %}
{% else %}

No reviews for this wine yet

{% endif %}

Add your review

{% if error_message %}

{{ error_message }}

{% endif %}
{% csrf_token %} {% bootstrap_form form layout='inline' %} {% buttons %} {% endbuttons %}
{% endblock %}

Это приводит к следующей веб-странице.

введите описание изображения здесь

Посмотрите, как сначала нам нужно импортировать {% load bootstrap 3%} , чтобы использовать Bootstrap 3 для тегов Django (например, тот, который мы используем в форме). Помимо классов, добавленных в div, мы использовали директиву {% bootstrap_form form %} для того, чтобы сделать формальный загрузчик загрузочным, включая кнопку со значком со звездочкой.

Этот пункт проекта, последний этап для этой части урока, соответствует тегу git stage-1 .

Выводы и будущая работа

В этом уроке мы объяснили, как настроить кодинг в качестве сервера разработки Django/Pandas. Затем мы запустили проект Django и приложение Django для нашего веб-приложения Wine recommender. Мы добавили некоторые объекты модели и объяснили, как создавать для них представления и формы. Мы закрыли эту первую часть урока, добавив некоторый стиль с помощью Bootstrap.

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

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