Автор оригинала: Jose A Dianes.
Это второй учебник из нашей серии о том, как создавать продукты данных с помощью Python. Помните, что в качестве лейтмотива мы хотим создать веб-сайт с обзорами и рекомендациями вин, используя технологии Python, такие как Django и Pandas. Мы решили создать веб-сайт отзывов и рекомендаций о вине, но концепции и технологический стек могут быть применены к любому продукту отзывов и рекомендаций пользователей.
Мы хотим, чтобы эти учебные пособия оставили вам продукт, который вы можете адаптировать и показать как часть своего портфолио. С этой целью мы объясним, как настроить виртуальную машину Koding и использовать ее в качестве сервера разработки Django и Pandas + Scikit-learn Python.
В первом уроке мы запустили проект Django и приложение Django для нашего веб-приложения Wine recommender. Все это будет постепенным процессом, за которым может последовать проверка отдельных тегов в нашем репо GitHub . Таким образом, вы можете работать над теми отдельными задачами на данном этапе, которые вам кажутся более интересными или трудными.
В этом втором уроке мы добавим управление пользователями. Это важная часть. Как только мы сможем идентифицировать отдельных пользователей, мы будем готовы генерировать рекомендации пользователей с помощью машинного обучения.
В третьем уроке вы узнаете, как использовать машинное обучение для предоставления рекомендаций нашим пользователям, используя кластеризацию k-means.
Помните, что вы можете следовать учебнику на любом этапе разработки, разветвив репо в свою учетную запись GitHub, а затем клонировав его в свою рабочую область и проверив соответствующий тег. Разветвляя репо, вы можете изменять его по своему усмотрению и экспериментировать с ним столько, сколько вам нужно. Если в какой-то момент вам захочется немного помочь с каким-то шагом урока или сделать его своим собственным, мы можем провести сеанс 1:1 codementor об этом.
Так что давайте продолжим наш проект!
Настройка аутентификации Django
С того самого момента , как мы создали наш проект с помощью django-admin startproject
, все модули для аутентификации пользователей были активированы. Они состоят из двух элементов, перечисленных в нашем INSTALLED_APPS
in settings.py
:
django.contrib.auth
содержит ядро платформы аутентификации и ее модели по умолчанию.django.contrib.contenttypes
– это система типов контента Django, которая позволяет связывать разрешения с моделями, которые вы создаете.
и эти элементы в настройках MIDDLEWARE_CLASSES
:
Промежуточное программное обеспечение сеанса
управляет сеансами между запросами.Промежуточное программное обеспечение аутентификации
связывает пользователей с запросами с помощью сеансов.SessionAuthenticationMiddleware
выводит пользователей из других сеансов после смены пароля.
С этими настройками на месте, когда мы выполнили команду manage.py миграция
мы уже создали необходимые таблицы базы данных для моделей, связанных с проверкой подлинности, и разрешений для любых моделей, определенных в наших установленных приложениях. На самом деле, мы можем увидеть их на сайте администратора, в разделе Пользователи.
Но мы хотим сделать по крайней мере две вещи. Сначала мы хотим потребовать аутентификации для некоторых действий в нашем веб-приложении (например, при добавлении нового обзора wine). Во-вторых, мы хотим, чтобы пользователи могли зарегистрироваться и войти в систему с помощью нашего веб-приложения (а не через сайт администратора).
Ограничение доступа к зарегистрированным пользователям
Теперь давайте признаем, что мы можем просто создавать пользователей с помощью интерфейса администратора. Перейдите туда и создайте пользователя, которого мы будем использовать в этом разделе. Если мы недавно использовали интерфейс администратора, мы, вероятно, продолжим входить в систему как администратор. Пока все в порядке.
Следующее, что мы хотим сделать,-это ограничить доступ к нашему представлению add_review
, чтобы его могли использовать только зарегистрированные пользователи.
Чистый и элегантный способ ограничения доступа к представлениям-это использование аннотации @login_required
. Измените функцию add_review
в reviews/views.py
итак, это выглядит так:
@login_required 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'] user_name = request.user.username 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})
Мы сделали две модификации. Первый-добавить аннотацию @login_required
. Таким образом, мы разрешаем доступ к этой функции просмотра только зарегистрированным пользователям. Во-вторых, использовать request.user.username
в качестве имени пользователя для наших обзоров. Объект запроса имеет ссылку на активного пользователя, и этот экземпляр имеет поле username
, которое мы можем использовать по мере необходимости.
Поскольку нам больше не нужно поле имени пользователя в форме, мы можем изменить этот класс формы в reviews/forms.py
следующим образом.
class ReviewForm(ModelForm): class Meta: model = Review fields = ['rating', 'comment'] widgets = { 'comment': Textarea(attrs={'cols': 40, 'rows': 15}), }
Если пользователь не вошел в систему, он будет перенаправлен на страницу входа в систему. Вы можете попробовать это, выйдя из системы на странице администратора, а затем попытавшись добавить обзор вина.
Если вы попытаетесь это сделать, вы увидите ошибку Страница не найдена (404)
, так как мы не определили сопоставление URL-адреса с запросом страницы входа в систему, а также не определили шаблон для него. Также обратите внимание, что URL-адрес, на который вы перенаправлены, включает в себя next=...
параметр, который будет целевой страницей после того, как мы правильно войдем в систему.
Просмотры входа в систему
Django предоставляет несколько представлений, которые можно использовать для управления логином, выходом из системы и паролем. Мы будем использовать их здесь. Так что все по порядку. Измените список urlpatterns
в winerama/urls.py
и оставьте его следующим образом.
urlpatterns = [ url(r'^reviews/', include('reviews.urls', namespace="reviews")), url(r'^admin/', include(admin.site.urls)), url('^accounts/', include('django.contrib.auth.urls')) ]
Мы только что импортировали все сопоставления из django.contrib.auth.url-адреса
. Теперь нам нужны шаблоны для различных веб-страниц управления пользователями. Они должны быть помещены в шаблоны/регистрация
в корневую папку для нашего проекта Django.
Например, создайте там login.html
шаблон со следующим кодом:
{% extends 'base.html' %} {% load bootstrap3 %} {% block title %}{% endblock %}Login
{% endblock %} {% block content %}
Чтобы наши шаблоны были доступны, нам нужно изменить список TEMPLATES
в winerama/settings.py
чтобы включить эту папку.
TEMPLATES = [ { 'BACKEND': 'django.template.backends.django.DjangoTemplates', 'DIRS': [os.path.join(BASE_DIR, 'templates')], 'APP_DIRS': True, 'OPTIONS': { 'context_processors': [ 'django.template.context_processors.debug', 'django.template.context_processors.request', 'django.contrib.auth.context_processors.auth', 'django.contrib.messages.context_processors.messages', ], }, }, ]
Нам нужно создать шаблоны для каждого представления управления пользователями. В этом разделе мы просто приведем два: templates/registration/login.html
и ‘templates/registration/logged_out.html”. Мы также переместим reviews/templates/reviews/base.html
шаблон к основному templates/base.html
папка, чтобы ее можно было использовать по всему проекту. Поэтому нам нужно обновить все директивы шаблона {% extend … % }, которые использовали его.
Проверьте репо GitHub , чтобы узнать, как должны выглядеть html-шаблоны.
Добавление элементов управления сеансом
Следующее, что нам нужно сделать, – это предоставить кнопки входа и выхода в нашем меню. Перейти к templates/base.html
и измените элемент в шаблоне, содержащем меню навигации, чтобы он выглядел следующим образом.
Важная часть здесь заключается в том, как мы используем контекстный объект user.is_authenticated
в выражении {% if%}
, чтобы показать правильные элементы меню. Когда пользователь вошел в систему, мы показываем кнопку выхода из системы и наоборот.
Если бы вы попробовали, вы, вероятно, заметили, что при входе в систему через меню мы получим ошибку 404 при попытке перейти на страницу профиля пользователя. Все в порядке. Мы еще не предоставили страницу профиля пользователя. Мы решим этот вопрос в следующем разделе.
Опять же, эта точка проекта соответствует тегу git stage-1.1
.
Страница Профиля пользователя
На самом деле наш профиль пользователя будет состоять из списка отзывов вошедшего в систему пользователя. Для этого нам понадобится несколько вещей:
- Нам нужно определить сопоставление по умолчанию для целевой страницы после входа в систему (когда параметр
next
не указан). - Затем нам нужно определить отображение для нового представления, которое мы собираемся добавить.
- Нам нужно определить функцию просмотра, которая возвращает отзывы, предоставленные пользователем.
- Нам нужно определить шаблон для отображения результата предыдущего представления.
- Для этого нам нужно создать пункт меню.
Давайте начнем с определения сопоставления по умолчанию. Это делается на уровне конфигурации проекта. Перейти к winerama/settings.py
и добавьте следующую строку.
LOGIN_REDIRECT_URL = '/reviews/review/user'
Теперь нам нужно определить сопоставления в reviews/urls.py
как показано в репозитории GitHub на этапе 1.2 (прямо сейчас у нас возникли проблемы с отображением этого фрагмента кода в строке, поэтому вам нужно будет взглянуть на него там, на GitHub).
Там мы указываем два сопоставления. Один используется, когда передается имя пользователя, а другой – когда его нет. Для нового представления требуется функция в reviews/views.py
, имена user_review_list
как определено в сопоставлении URL-адресов. Добавьте следующее в файл представления.
def user_review_list(request, username=None): if not username: username = request.user.username latest_review_list = Review.objects.filter(user_name=username).order_by('-pub_date') context = {'latest_review_list':latest_review_list, 'username':username} return render(request, 'reviews/user_review_list.html', context)
Как вы видите, мы просто добавили фильтр к коду, который мы использовали в списке последних обзоров, а затем использовали новое имя шаблона user_review_list.html
. Мы могли бы использовать существующий шаблон для review_list.html
, но мы хотим изменить название на что-то более специфичное для пользователя. Наконец, мы можем решить, следует ли требовать от пользователей входа в систему для этого представления. Если нет (как мы это сделали), отзывы пользователей являются общедоступными, поэтому пользователи, которые не вошли в систему, также могут их просматривать.
Далее нам нужно создать шаблон следующим образом.
{% extends 'reviews/review_list.html' %} {% block title %}Reviews by {{ user.username }}
{% endblock %}
То есть мы расширяем review_list.html
шаблон и просто определите {% заголовок блока%}
, чтобы заменить заголовок на тот, который включает имя пользователя.
Наконец, давайте добавим пункт меню для нового представления. Нам нужна ссылка с надписью Hello USER_NAME рядом с пунктом меню выход из системы|/. Перейдите и измените элемент в
templates/base.html таким образом, это выглядит следующим образом (посмотрите на файл
GitHub stage-1.2 , если у вас возникли проблемы с отображением html-тегов ниже).
Наконец, мы хотим иметь возможность переходить на страницы отзывов других пользователей. Например, когда мы видим имя пользователя в обзоре wine, мы хотим иметь возможность щелкнуть его имя и перейти на страницу отзывов пользователей. Это означает, что нам нужно обновить review_list.html
и review_detail.html
шаблоны и замените текст имени пользователя элементом следующим образом (это
reviews_detail.html
шаблон).
{% extends 'base.html' %} {% block title %}{{ review.wine.name }}
{% endblock %} {% block content %}Rated {{ review.rating }} of 5 by {{ review.user_name }}
{{ review.pub_date }}
{{ review.comment }}
{% endblock %}
Вы можете перейти в stage-1.2
, чтобы посмотреть, как эти файлы выглядят после обновлений.
И это все. Мы создали правильную целевую страницу пользователя. Он такой же, как и список отзывов, но отфильтрован, чтобы включать только эти отзывы пользователей. Это представление также можно использовать для проверки конкретных отзывов пользователей. Этот пункт проекта соответствует тегу git stage-1.2
.
Страница регистрации
У нас уже есть возможность создавать пользователей, но только через интерфейс администратора (или с помощью кода). Мы хотим, чтобы незарегистрированный пользователь мог зарегистрироваться и создать свою собственную учетную запись пользователя. Мы могли бы создавать формы и представления для этого, но есть очень хорошее приложение для регистрации Django , которое мы можем установить и использовать для этого.
Давайте начнем с установки пакета приложений с помощью нашего pip Anaconda следующим образом. Предположим, что мы находимся в папке, содержащей установку anaconda:
./anaconda/bin/pip install django-registration-redux
Если все пойдет хорошо, нам нужно добавить приложение в список INSTALLED_APPS
в winerama/settings.py
следующим образом:
INSTALLED_APPS = ( 'django.contrib.admin', 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', 'django.contrib.messages', 'django.contrib.staticfiles', 'bootstrap3', 'reviews', 'registration', )
Добавьте также следующие значения в файл настроек.
ACCOUNT_ACTIVATION_DAYS = 7 # One-week activation window REGISTRATION_AUTO_LOGIN = True # Automatically log the user in.
Как только мы это сделаем, нам нужно установить модель, используемую настройкой по умолчанию. Из терминала в корне проекта выполните следующие действия.
python manage.py makemigrations
И затем
pythonmanage.py migrate
Приложение включает в себя различные представления управления пользователями, но мы хотим использовать только регистрационные. Установите следующее в поле winerama/urls.py
файл.
urlpatterns = [ url(r'^reviews/', include('reviews.urls', namespace="reviews")), url(r'^admin/', include(admin.site.urls)), url(r'^accounts/', include('registration.backends.simple.urls')), url(r'^accounts/', include('django.contrib.auth.urls', namespace="auth")), ]
Нам нужно предоставить два шаблона, которые заменят шаблоны по умолчанию. Мы хотим, чтобы наш сайт больше соответствовал стилю нашего сайта. Они и есть `templates/registration/registration_form.html” и “templates/registration/registration_complete.html”. Первый выглядит так.
{% extends 'base.html' %} {% load bootstrap3 %} {% block title %}{% endblock %}Register
{% endblock %} {% block content %}
Там мы просто следуем той же структуре, которую мы использовали для шаблона входа в систему. Ничего особенного. Тот, который для регистрации завершен, выглядит следующим образом.
{% extends 'base.html' %} {% load bootstrap3 %} {% block title %}Register
{% endblock %} {% block content %} Thanks for registering! {% endblock %}
Они должны быть названы таким образом и находиться в основной папке templates/registration
для django-registration
, чтобы найти их.
Мы только что использовали самый простой подход к созданию функции регистрации пользователей. Если вы заинтересованы в более сложном (и готовом к производству) подходе, например, отправке пользователю писем с подтверждением активации/подтверждением или представлениях восстановления/сброса пароля, ознакомьтесь с документами регистрации Django . Основная проблема с их использованием в этом уроке заключается в том, что они связаны с использованием сервера электронной почты, и это не очень связано с тем, чему мы хотим научить здесь.
Эта точка проекта соответствует тегу git stage-2
репо проекта.
Выводы
В этой части урока мы ввели пользователей и управление пользователями в наше приложение Django. Требуя регистрации пользователей, мы сможем собирать лучшую статистику пользователей, и это является фундаментальным шагом в создании рекомендаций на основе пользователей.
Однако наше управление пользователями было очень наивным и простым. Есть много проблем, которые нам необходимо решить, если мы хотим запустить эту систему в производство, например, обеспечить двухэтапный процесс активации учетных записей пользователей, проверить, использовалась ли ранее электронная почта, или даже разрешить пользователям регистрироваться в своих социальных сетях.
Но того, что мы сделали до сих пор, достаточно для нашей конечной цели-показать, как веб-сайт может включать рекомендательную систему и каков его рабочий процесс при сборе пользовательских данных. Наша конечная цель-построить модели для предоставления рекомендаций. Это будет целью третьей и последней части нашего урока.
Помните, что вы можете следовать учебнику на любом этапе разработки, разветвляя репо в свою учетную запись GitHub, а затем клонируя в свою рабочую область и проверяя соответствующий тег. Разветвляя репо, вы можете изменять его по своему усмотрению и экспериментировать с ним столько, сколько вам нужно. Если в какой-то момент вам захочется немного помочь с каким-то шагом урока или сделать его своим собственным, мы можем провести сеанс 1:1 Codementor об этом.