From c058fa0fb22dc40ef0225b21a97578cddd0aaffa Mon Sep 17 00:00:00 2001 From: Florian Merz Date: Thu, 11 Feb 2021 14:51:05 +0100 Subject: unslug ru: move --- .../server-side/django/authentication/index.html | 688 +++++++++++++++++++++ .../learn/server-side/django/deployment/index.html | 680 ++++++++++++++++++++ .../server-side/django/introduction/index.html | 257 ++++++++ .../learn/server-side/django/sessions/index.html | 181 ++++++ .../index.html" | 688 --------------------- .../index.html" | 257 -------- .../index.html" | 680 -------------------- .../index.html" | 181 ------ 8 files changed, 1806 insertions(+), 1806 deletions(-) create mode 100644 files/ru/learn/server-side/django/authentication/index.html create mode 100644 files/ru/learn/server-side/django/deployment/index.html create mode 100644 files/ru/learn/server-side/django/introduction/index.html create mode 100644 files/ru/learn/server-side/django/sessions/index.html delete mode 100644 "files/ru/learn/server-side/django/\320\260\321\203\321\202\320\265\320\275\321\202\320\270\321\204\320\270\320\272\320\260\321\206\320\270\321\217/index.html" delete mode 100644 "files/ru/learn/server-side/django/\320\262\320\262\320\265\320\264\320\265\320\275\320\270\320\265/index.html" delete mode 100644 "files/ru/learn/server-side/django/\321\200\320\260\320\267\320\262\320\276\321\200\320\260\321\207\320\270\320\262\320\260\320\275\320\270\320\265/index.html" delete mode 100644 "files/ru/learn/server-side/django/\321\201\320\265\321\201\321\201\320\270\320\270/index.html" (limited to 'files/ru/learn/server-side/django') diff --git a/files/ru/learn/server-side/django/authentication/index.html b/files/ru/learn/server-side/django/authentication/index.html new file mode 100644 index 0000000000..807db42a90 --- /dev/null +++ b/files/ru/learn/server-side/django/authentication/index.html @@ -0,0 +1,688 @@ +--- +title: 'Руководство Django Часть 8: Аутентификация и авторизация пользователя' +slug: Learn/Server-side/Django/Аутентификация +tags: + - Python + - Аутентификация + - Аутентификация django + - Джанго + - Начинающий + - Обучение + - Разграничение доступа + - Руководство + - Сервер + - Статья + - Формы + - на стороне сервера + - сессии +translation_of: Learn/Server-side/Django/Authentication +--- +
{{LearnSidebar}}
+ +
{{PreviousMenuNext("Learn/Server-side/Django/Sessions", "Learn/Server-side/Django/Forms", "Learn/Server-side/Django")}}
+ +

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

+ + + + + + + + + + + + +
Требования:Завершить изучение предыдущих тем руководства, включая Руководство Django Часть 7: Работа с сессиями.
Цель:Понимать как настроить и использовать механизм аутентификации пользователя и разграничений прав доступа.
+ +

Обзор

+ +

Django предоставляет систему аутентификации и авторизации ("permission") пользователя, реализованную на основе фреймворка работы с сессиями, который мы рассматривали в предыдущей части. Система аутентификации и авторизации позволяет вам проверять учетные данные пользователей и определять какие действия какой пользователь может выполнять. Данный фреймворк включает в себя встроенные модели для Пользователей и Групп (основной способ применения прав доступа для более чем одного пользователя), непосредственно саму систему прав доступа (permissions)/флаги, которые определяют может ли пользователь выполнить задачу, с какой формой и отображением для авторизованых пользователей, а так же получить доступ к контенту с ограниченым доступом.

+ +
+

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

+
+ +

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

+ +

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

+ +

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

+ +

Подключение аутентификации

+ +

Аутентификация была подключена автоматически когда мы создали скелет сайта (в части 2), таким образом на данный момент вам ничего не надо делать.

+ +
+

Примечание: Необходимые настройки были выполнены для нас, когда мы создали приложение при помощи команды django-admin startproject. Таблицы базы данных для пользователей и модели авторизации были созданы, когда в первый раз выполнили команду python manage.py migrate.

+
+ +

Соответствующие настройки сделаны в параметрах INSTALLED_APPS и MIDDLEWARE файла проекта (locallibrary/locallibrary/settings.py), как показано ниже:

+ +
INSTALLED_APPS = [
+    ...
+    'django.contrib.auth',  # Фреймворк аутентификации и моделей по умолчанию.
+    'django.contrib.contenttypes',  # Django контент-типовая система (даёт разрешения, связанные с моделями).
+    ....
+
+MIDDLEWARE = [
+    ...
+    'django.contrib.sessions.middleware.SessionMiddleware',  # Управление сессиями между запросами
+    ...
+    'django.contrib.auth.middleware.AuthenticationMiddleware',  # Связывает пользователей, использующих сессии, запросами.
+    ....
+
+ +

Создание пользователей и групп

+ +

Вы уже создали своего первого пользователя когда мы рассматривали Административная панель сайта Django в части 4 (это был суперпользователь, созданный при помощи команды python manage.py createsuperuser). Наш суперпользователь уже авторизован и имеет все необходимые уровни доступа к данным и функциям, таким образом нам необходимо создать тестового пользователя для отработки соответствующей работы сайта. В качестве наиболее быстрого способа, мы будем использовать административную панель сайта для создания соответствующих групп и акканутов locallibrary.

+ +
+

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

+ +
from django.contrib.auth.models import User
+
+# Создайте пользователя и сохраните его в базе данных
+user = User.objects.create_user('myusername', 'myemail@crazymail.com', 'mypassword')
+
+# Обновите поля и сохраните их снова
+user.first_name = 'John'
+user.last_name = 'Citizen'
+user.save()
+
+
+ +

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

+ +

Запустите сервер разработки и перейдите к административной панели вашего сайта (http://127.0.0.1:8000/admin/). Залогиньтесь на сайте при помощи параметров (имя пользователя и пароля) аккаунта суперпользователя. Самая "верхняя" страница панели Администратора показывает все наши модели. Для того, чтобы увидеть записи в разделе Authentication and Authorisation вы можете нажать на ссылку Users, или Groups.

+ +

Admin site - add groups or users

+ +

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

+ +
    +
  1. Нажмите на кнопку Add (Добавить) (рядом с Group) и создайте новую группу; для данной группы введите Name (Имя) "Library Members".Admin site - add group
  2. +
  3. Для данной группы не нужны какие-либо разрешения, поэтому мы просто нажимаем кнопку SAVE (Сохранить) (вы перейдете к списку групп).
  4. +
+ +

Теперь давайте создадим пользователя:

+ +
    +
  1. Перейдите обратно на домашнюю страницу административной панели
  2. +
  3. Для перехода к диалогу добавления пользователя нажмите на кнопку Add, соответствующую строке Users (Пользователи).Admin site - add user pt1
  4. +
  5. Введите соответствующие Username (имя пользователя) и Password/Password confirmation (пароль/подтверждение пароля) для вашего тестового пользователя
  6. +
  7. Нажмите SAVE для завершения процесса создания пользователя.
    +
    + Административная часть сайта создаст нового пользователя и немедленно перенаправит вас на страницу Change user (Изменение параметров пользователя) где вы можете, соответственно, изменить ваш username, а кроме того добавить информацию для дополнительных полей модели User. Эти поля включают в себя имя пользователя, фамилию, адрес электронной почты, статус пользователя, а также соответствующие параметры доступа (может быть установлен только флаг  Active). Ниже вы можете определить группу для пользователя и необходимые параметры доступа, а кроме того, вы можете увидеть важные даты, относящиеся к пользователю (дату подключения к сайту и дату последнего входа).Admin site - add user pt2
  8. +
  9. В разделе Groups, из списка Доступные группы выберите группу Library Member, а затем переместите ее в блок "Выбранные группы" (нажмите стрелку-"направо", находящуюся между блоками).Admin site - add user to group
  10. +
  11. Больше нам не нужно здесь нечего делать, просто нажмите "Save"(Сохранить), и вы вернетесь к списку созданых пользователей.
  12. +
+ +

Вот и все! Теперь у вас есть учетная запись «обычного члена библиотеки», которую вы сможете использовать для тестирования (как только добавим страницы, чтобы пользователи могли войти в систему).

+ +
+

Note: Попробуйте создать другого пользователя, например "Библиотекаря". Так же создайте группу "Библиотекарей" и добавьте туда своего только что созданного библиотекаря

+
+ +

Настройка представлений проверки

+ +

Django предоставляет почти все, что нужно для создания страниц аутентификации входа, выхода из системы и управления паролями из коробки. Это включает в себя url-адреса, представления (views) и формы,но не включает шаблоны — мы должны создать свой собственный шаблон!

+ +

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

+ +
+

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

+
+ +
+

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

+
+ +

Проектирование URLs

+ +

Добавьте следующее в нижней части проекта urls.py файл (locallibrary/locallibrary/urls.py) файл:

+ +
#Add Django site authentication urls (for login, logout, password management)
+urlpatterns += [
+    path('accounts/', include('django.contrib.auth.urls')),
+]
+
+ +

Перейдите по http://127.0.0.1:8000/accounts/ URL (обратите внимание на косую черту!), Django покажет ошибку, что он не смог найти этот URL, и перечислить все URL, которые он пытался открыть. Из этого Вы можете увидеть URL-адреса, которые будут работать, например:

+ +
+

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

+
+ +
+
accounts/ login/ [name='login']
+accounts/ logout/ [name='logout']
+accounts/ password_change/ [name='password_change']
+accounts/ password_change/done/ [name='password_change_done']
+accounts/ password_reset/ [name='password_reset']
+accounts/ password_reset/done/ [name='password_reset_done']
+accounts/ reset/<uidb64>/<token>/ [name='password_reset_confirm']
+accounts/ reset/done/ [name='password_reset_complete']
+
+ +

Теперь попробуйте перейти к URL-адресу входа (http://127.0.0.1:8000/accounts/login/). Это приведет к сбою снова, но с ошибкой, сообщающей вам, что нам не хватает требуемого шаблона (registration / login.html) в пути поиска шаблона. Вы увидите следующие строки, перечисленные в желтом разделе вверху:

+ +
Exception Type:    TemplateDoesNotExist
+Exception Value:    registration/login.html
+ +

Следующий шаг - создать каталог регистрации в пути поиска, а затем добавить файл login.html.

+ +

Каталог шаблонов

+ +

URL-адреса (и неявные представления), которые мы только что добавили, ожидают найти связанные с ними шаблоны в каталоге / регистрации / где-то в пути поиска шаблонов.
+
+ Для этого сайта мы разместим наши HTML-страницы в каталоге templates / registration /. Этот каталог должен находиться в корневом каталоге проекта, то есть в том же каталоге, что и в каталоге и папках locallibrary). Создайте эти папки сейчас.

+ +
+

Примечание: Ваша структура папок теперь должна выглядеть как показано внизу:
+ locallibrary (django project folder)
+    |_catalog
+    |_locallibrary
+    |_templates (new)
+                 |_registration

+
+ +

Чтобы сделать эти директории видимыми для загрузчика шаблонов   (т. е. помещать этот каталог в путь поиска шаблона) откройте настройки проекта (/locallibrary/locallibrary/settings.py), и обновите в секции TEMPLATES строку 'DIRS' как показано.

+ +
TEMPLATES = [
+    {
+        ...
+        'DIRS': [os.path.join(BASE_DIR, 'templates')],
+        'APP_DIRS': True,
+        ...
+
+ +

Шаблон аутентификации

+ +
+

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

+
+ +

Создайте новый HTML файл, названный /locallibrary/templates/registration/login.html. дайте ему следующее содержание:

+ +
{% extends "base_generic.html" %}
+
+{% block content %}
+
+{% if form.errors %}
+  <p>Your username and password didn't match. Please try again.</p>
+{% endif %}
+
+{% if next %}
+  {% if user.is_authenticated %}
+    <p>Your account doesn't have access to this page. To proceed,
+    please login with an account that has access.</p>
+  {% else %}
+    <p>Please login to see this page.</p>
+  {% endif %}
+{% endif %}
+
+<form method="post" action="{% url 'login' %}">
+{% csrf_token %}
+<table>
+
+<tr>
+  <td>\{{ form.username.label_tag }}</td>
+  <td>\{{ form.username }}</td>
+</tr>
+
+<tr>
+  <td>\{{ form.password.label_tag }}</td>
+  <td>\{{ form.password }}</td>
+</tr>
+</table>
+
+<input type="submit" value="login" />
+<input type="hidden" name="next" value="\{{ next }}" />
+</form>
+
+{# Assumes you setup the password_reset view in your URLconf #}
+<p><a href="{% url 'password_reset' %}">Lost password?</a></p>
+
+{% endblock %}
+ +

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

+ +

Перейдите на страницу входа (http://127.0.0.1:8000/accounts/login/) когда вы сохраните свой шаблон, и вы должны увидеть что-то наподобие этого:

+ +

Library login page v1

+ +

Если ваша попытка войти в систему будет успешной,  вы будете перенаправлены на другую страницу (по умолчанию это будет http://127.0.0.1:8000/accounts/profile/). Проблема здесь в том, что по умолчанию Django ожидает, что после входа в систему вы захотите перейти на страницу профиля, что может быть или не быть. Поскольку вы еще не определили эту страницу, вы получите еще одну ошибку!
+
+ Откройте настройки проекта (/locallibrary/locallibrary/settings.py) и добавьте текст ниже. Теперь, когда вы входите в систему, вы по умолчанию должны перенаправляться на домашнюю страницу сайта.

+ +
# Redirect to home URL after login (Default redirects to /accounts/profile/)
+LOGIN_REDIRECT_URL = '/'
+
+ +

Шаблон выхода

+ +

Если вы перейдете по URL-адресу выхода (http://127.0.0.1:8000/accounts/logout/), то увидите странное поведение - ваш пользователь наверняка выйдет из системы, но вы попадете на страницу выхода администратора. Это не то, что вам нужно, хотя бы потому, что ссылка для входа на этой странице приведет вас к экрану входа в систему администратора. (и это доступно только для пользователей, у которых есть разрешение is_staff).
+
+ Создайте и откройте /locallibrary/templates/registration/logged_out.html. Скопируйте текст ниже:

+ +
{% extends "base_generic.html" %}
+
+{% block content %}
+<p>Logged out!</p>
+
+<a href="{% url 'login'%}">Click here to login again.</a>
+{% endblock %}
+ +

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

+ +

Library logout page v1

+ +

Шаблон сброса пароля

+ +

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

+ +

Форма сброса пароля

+ +

Это форма, используемая для получения адреса электронной почты пользователя (для отправки пароля для сброса пароля). Создайте /locallibrary/templates/registration/password_reset_form.html и дайте ему следующее содержание:

+ +
{% extends "base_generic.html" %}
+{% block content %}
+
+<form action="" method="post">{% csrf_token %}
+    {% if form.email.errors %} \{{ form.email.errors }} {% endif %}
+        <p>\{{ form.email }}</p>
+    <input type="submit" class="btn btn-default btn-lg" value="Reset password" />
+</form>
+
+{% endblock %}
+
+ +

Сброс пароля

+ +

Эта форма отображается после того, как ваш адрес электронной почты будет собран. Создайте /locallibrary/templates/registration/password_reset_done.html, и дайте ему следующее содержание:

+ +
{% extends "base_generic.html" %}
+{% block content %}
+<p>We've emailed you instructions for setting your password. If they haven't arrived in a few minutes, check your spam folder.</p>
+{% endblock %}
+
+ +

Сброс пароля по email

+ +

Этот шаблон предоставляет текст электронной почты HTML, содержащий ссылку на сброс, которую мы отправим пользователям. Создайте /locallibrary/templates/registration/password_reset_email.html и дайте ему следующее содержание:

+ +
Someone asked for password reset for email \{{ email }}. Follow the link below:
+\{{ protocol}}://\{{ domain }}{% url 'password_reset_confirm' uidb64=uid token=token %}
+
+ +

Подтверждение на сброс пароля

+ +

На этой странице вы вводите новый пароль после нажатия ссылки в электронном письме с возвратом пароля. Создайте /locallibrary/templates/registration/password_reset_confirm.html и дайте ему следующее содержание:

+ +
{% extends "base_generic.html" %}
+
+{% block content %}
+
+    {% if validlink %}
+        <p>Please enter (and confirm) your new password.</p>
+        <form action="" method="post">
+            {% csrf_token %}
+            <table>
+                <tr>
+                    <td>\{{ form.new_password1.errors }}
+                        <label for="id_new_password1">New password:</label></td>
+                    <td>\{{ form.new_password1 }}</td>
+                </tr>
+                <tr>
+                    <td>\{{ form.new_password2.errors }}
+                        <label for="id_new_password2">Confirm password:</label></td>
+                    <td>\{{ form.new_password2 }}</td>
+                </tr>
+                <tr>
+                    <td></td>
+                    <td><input type="submit" value="Change my password" /></td>
+                </tr>
+            </table>
+        </form>
+    {% else %}
+        <h1>Password reset failed</h1>
+        <p>The password reset link was invalid, possibly because it has already been used. Please request a new password reset.</p>
+    {% endif %}
+
+{% endblock %}
+
+ +

Сброс пароля завершен

+ +

Это последний шаблон сброса пароля, который отображается, чтобы уведомить вас о завершении сброса пароля. Создайте /locallibrary/templates/registration/password_reset_complete.html и дайте ему следующее содержание:

+ +
{% extends "base_generic.html" %}
+{% block content %}
+
+<h1>The password has been changed!</h1>
+<p><a href="{% url 'login' %}">log in again?</a></p>
+
+{% endblock %}
+ +

Тестирование новых страниц аутентификации

+ +

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

+ + + +

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

+ +
+

Заметка: Система сброса пароля требует, чтобы ваш сайт поддерживал электронную почту, что выходит за рамки этой статьи, поэтому эта часть еще не будет работать. Чтобы разрешить тестирование, поместите следующую строку в конец файла settings.py. Это регистрирует любые письма, отправленные на консоль (чтобы вы могли скопировать ссылку на сброс пароля с консоли).

+ +
EMAIL_BACKEND = 'django.core.mail.backends.console.EmailBackend'
+
+ +

Для получения дополнительной информации см. Отправка email (Django docs).

+
+ +

Тестирование проверки подлинности пользователей

+ +

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

+ +

Тестирование в шаблонах

+ +

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

+ +

Обычно вы сначала проверяете переменную шаблона \{{user.is_authenticated}}, чтобы определить, имеет ли пользователь право видеть конкретный контент. Чтобы продемонстрировать это, мы обновим нашу боковую панель, чтобы отобразить ссылку «Вход», если пользователь вышел из системы, и ссылку «Выход», если он вошёл в систему.

+ +

Откройте базовый шаблон (/locallibrary/catalog/templates/base_generic.html) и скопируйте следующий текст в sidebar блок непосредственно перед тегом шаблона endblock.

+ +
  <ul class="sidebar-nav">
+
+    ...
+
+   {% if user.is_authenticated %}
+     <li>User: \{{ user.get_username }}</li>
+     <li><a href="{% url 'logout'%}?next=\{{request.path}}">Logout</a></li>
+   {% else %}
+     <li><a href="{% url 'login'%}?next=\{{request.path}}">Login</a></li>
+   {% endif %} 
+  </ul>
+ +

Как вы можете видеть, мы используем теги шаблона if-else-endif для условного отображения текста на основе того, является ли \{{user.is_authenticated}} истинным. Если пользователь аутентифицирован, мы знаем, что у нас есть действительный пользователь, поэтому мы вызываем \{{user.get_username}}, чтобы отобразить их имя.

+ +

Мы создаем URL-адрес для входа и выхода из системы, используя тег шаблона URL-адреса и имена соответствующих конфигураций URLs. Также обратите внимание на то, как мы добавили ?next=\{{request.path}} в конец URLs. Это означает, что следующий URL-адрес содержит адрес (URL) текущей страницы, в конце связанного URL-адреса. После того, как пользователь успешно выполнил вход в систему, представления будут использовать значение "next" чтобы перенаправить пользователя обратно на страницу, где они сначала нажали ссылку входа / выхода из системы.

+ +
+

Примечание: Попробуйте! Если вы находитесь на главной странице и вы нажимаете «Вход / Выход» на боковой панели, то после завершения операции вы должны вернуться на ту же страницу.

+
+ +

Тестирование в представлениях

+ +

Если вы используете функциональные представления, самым простым способом ограничить доступ к вашим функциям является применение login_required декоратор к вашей функции просмотра, как показано ниже. Если пользователь вошел в систему, ваш код просмотра будет выполняться как обычно. Если пользователь не вошел в систему, это перенаправит URL-адрес входа, определенный в настройках проекта. (settings.LOGIN_URL), передав текущий абсолютный путь в качестве next параметра URL. Если пользователю удастся войти в систему, они будут возвращены на эту страницу, но на этот раз аутентифицированы.

+ +
from django.contrib.auth.decorators import login_required
+
+@login_required
+def my_view(request):
+    ...
+ +
+

Заметка: Вы можете сделать то же самое вручную, путём тестирования request.user.is_authenticated, но декоратор намного удобнее!

+
+ +

Аналогичным образом, самый простой способ ограничить доступ к зарегистрированным пользователям в ваших представлениях на основе классов - это производные от LoginRequiredMixin. Вы должны объявить этот mixin сначала в списке суперкласса, перед классом основного представления.

+ +
from django.contrib.auth.mixins import LoginRequiredMixin
+
+class MyView(LoginRequiredMixin, View):
+    ...
+ +

Это имеет такое же поведение при переадресации, что и  login_required декоратор. Вы также можете указать альтернативное местоположение для перенаправления пользователя, если он не аутентифицирован (login_url), и имя параметра URL вместо "next" , чтобы вставить текущий абсолютный путь (redirect_field_name).

+ +
class MyView(LoginRequiredMixin, View):
+    login_url = '/login/'
+    redirect_field_name = 'redirect_to'
+
+ +

Для получения дополнительной информации ознакомьтесь с  Django docs here.

+ +

Пример - перечисление книг текущего пользователя

+ +

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

+ +

К сожалению, у нас пока нет возможности пользователям использовать книги! Поэтому, прежде чем мы сможем создать список книг, мы сначала расширим BookInstance модель для поддержки концепции заимствования и использования приложения Django Admin для заимствования ряда книг нашему тестовому пользователю.

+ +

Модели

+ +

Прежде всего, мы должны предоставить пользователям возможность кредита на BookInstance (у нас уже есть status и due_back дата, но у нас пока нет связи между этой моделью и пользователем. Мы создадим его с помощью поля ForeignKey (один ко многим). Нам также нужен простой механизм для проверки того, просрочена ли заемная книга.

+ +

Откройте catalog/models.py, и импортируйте модель User из django.contrib.auth.models (добавьте это чуть ниже предыдущей строки импорта в верхней части файла, так User доступен для последующего кода, что позволяет использовать его):

+ +
from django.contrib.auth.models import User
+
+ +

Затем добавьте поле borrower в модель BookInstance:

+ +
borrower = models.ForeignKey(User, on_delete=models.SET_NULL, null=True, blank=True)
+
+ +

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

+ +
from datetime import date
+ +

Теперь добавьте следующее определение свойства внутри класса BookInstance:

+ +
@property
+def is_overdue(self):
+    if self.due_back and date.today() > self.due_back:
+        return True
+    return False
+ +
+

Примечание. Сначала мы проверим, является ли due_back пустым, прежде чем проводить сравнение. Пустое поле due_back заставило Django выкидывать ошибку, а не показывать страницу: пустые значения не сопоставимы. Это не то, что мы хотели бы, чтобы наши пользователи испытывали!

+
+ +

Теперь, когда мы обновили наши модели, нам нужно будет внести новые изменения в проект, а затем применить эти миграции:

+ +
python3 manage.py makemigrations
+python3 manage.py migrate
+
+ +

Admin

+ +

Теперь откройте каталог catalog/admin.py, и добавьте поле borrower в класс BookInstanceAdmin , как в list_display , так и в полях fieldsets , как показано ниже. Это сделает поле видимым в разделе Admin, так что мы можем при необходимости назначить User в BookInstance.

+ +
@admin.register(BookInstance)
+class BookInstanceAdmin(admin.ModelAdmin):
+    list_display = ('book', 'status', 'borrower', 'due_back', 'id')
+    list_filter = ('status', 'due_back')
+
+    fieldsets = (
+        (None, {
+            'fields': ('book','imprint', 'id')
+        }),
+        ('Availability', {
+            'fields': ('status', 'due_back','borrower')
+        }),
+    )
+ +

Займите несколько книг

+ +

Теперь, когда возможно кредитовать книги конкретному пользователю, зайдите и заработайте на нескольких записей в BookInstance. Установите borrowed поле вашему тестовому пользователю, сделайте status «В займе» и установите сроки оплаты как в будущем, так и в прошлом.

+ +
+

Заметка: Мы не будем описывать процесс, так как вы уже знаете, как использовать Admin сайт!

+
+ +

Займ в представлении

+ +

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

+ +

Добавьте следующее в catalog/views.py:

+ +
from django.contrib.auth.mixins import LoginRequiredMixin
+
+class LoanedBooksByUserListView(LoginRequiredMixin,generic.ListView):
+    """
+    Generic class-based view listing books on loan to current user.
+    """
+    model = BookInstance
+    template_name ='catalog/bookinstance_list_borrowed_user.html'
+    paginate_by = 10
+
+    def get_queryset(self):
+        return BookInstance.objects.filter(borrower=self.request.user).filter(status__exact='o').order_by('due_back')
+ +

Чтобы ограничить наш запрос только объектами BookInstance для текущего пользователя, мы повторно реализуем get_queryset(), как показано выше. Обратите внимание, что "o" это сохраненный код для "on loan" и мы сортируем по дате due_back, чтобы сначала отображались самые старые элементы.

+ +

URL-адрес для заёмных книг

+ +

Теперь откройте /catalog/urls.py и добавьте url() , указывая на приведённое выше представление (вы можете просто скопировать текст ниже в конец файла).

+ +
urlpatterns += [
+    url(r'^mybooks/$', views.LoanedBooksByUserListView.as_view(), name='my-borrowed'),
+]
+ +

Шаблон для заёмных книг

+ +

Теперь все, что нам нужно сделать для этой страницы, - это добавить шаблон. Сначала создайте файл шаблона /catalog/templates/catalog/bookinstance_list_borrowed_user.html и дайте ему следующее содержание:

+ +
{% extends "base_generic.html" %}
+
+{% block content %}
+    <h1>Borrowed books</h1>
+
+    {% if bookinstance_list %}
+    <ul>
+
+      {% for bookinst in bookinstance_list %}
+      <li class="{% if bookinst.is_overdue %}text-danger{% endif %}">
+        <a href="{% url 'book-detail' bookinst.book.pk %}">\{{bookinst.book.title}}</a> (\{{ bookinst.due_back }})
+      </li>
+      {% endfor %}
+    </ul>
+
+    {% else %}
+      <p>There are no books borrowed.</p>
+    {% endif %}
+{% endblock %}
+ +

Этот шаблон очень похож на тот, который мы создали ранее для объектов Book и Author. Единственное, что «новое» здесь, это то, что мы проверяем метод, который мы добавили в модель (bookinst.is_overdue) с целью использовать его для изменения цвета просроченных предметов.

+ +

Когда сервер разработки запущен, вы должны теперь иметь возможность просматривать список для зарегистрированного пользователя в своем браузере по адресу  http://127.0.0.1:8000/catalog/mybooks/. Попробуйте это, когда ваш пользователь войдет в систему и выйдет из системы (во втором случае вы должны быть перенаправлены на страницу входа в систему).

+ +

Добавить список на боковую панель

+ +

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

+ +

Откройте базовый шаблон (/locallibrary/catalog/templates/base_generic.html) и добавьте выделенную строку из sidebar, как показано на рисунке.

+ +
 <ul class="sidebar-nav">
+   {% if user.is_authenticated %}
+   <li>User: \{{ user.get_username }}</li>
+   <li><a href="{% url 'my-borrowed' %}">My Borrowed</a></li>
+   <li><a href="{% url 'logout'%}?next=\{{request.path}}">Logout</a></li>
+   {% else %}
+   <li><a href="{% url 'login'%}?next=\{{request.path}}">Login</a></li>
+   {% endif %}
+ </ul>
+
+ +

На что это похоже?

+ +

Когда любой пользователь войдет в систему, он будет видеть ссылку «Мной позаимствовано (My Borrowed)» в боковой колонке, и список книг, показанных ниже (первая книга не имеет установленной даты, что является ошибкой, которую мы надеемся исправить в более позднем уроке!).

+ +

Library - borrowed books by user

+ +

Права доступа

+ +

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

+ +

Модели

+ +

Определение разрешений выполняется в разделе моделей "class Meta" , используется permissions поле. Вы можете указать столько разрешений, сколько необходимо в кортеже, причем каждое разрешение определяется во вложенном кортеже, содержащем имя разрешения и отображаемое значение разрешения. Например, мы можем определить разрешение, позволяющее пользователю отметить, что книга была возвращена, как показано здесь:

+ +
class BookInstance(models.Model):
+    ...
+    class Meta:
+        ...
+        permissions = (("can_mark_returned", "Set book as returned"),)   
+ +

Затем мы могли бы назначить разрешение группе «Библиотекарь» (Librarian) на сайте администратора.

+ +

Откройте catalog/models.py, и добавьте разрешение, как показано выше. Вам нужно будет повторно выполнить миграцию (вызвав python3 manage.py makemigrations и python3 manage.py migrate) для надлежащего обновления базы данных.

+ +

Шаблоны

+ +

Разрешения текущего пользователя хранятся в переменной шаблона, называемой  \{{ perms }}. Вы можете проверить, имеет ли текущий пользователь определенное разрешение, используя конкретное имя переменной в соответствующем приложении «Django» - например, \{{ perms.catalog.can_mark_returned }} будет True если у пользователя есть это разрешение, а False - в противном случае. Обычно мы проверяем разрешение с использованием шаблона {% if %}, как показано в:

+ +
{% if perms.catalog.can_mark_returned %}
+    <!-- We can mark a BookInstance as returned. -->
+    <!-- Perhaps add code to link to a "book return" view here. -->
+{% endif %}
+
+ +

Представления

+ +

Разрешения можно проверить в представлении функции, используя  permission_required декоратор или в представлении на основе классов, используя PermissionRequiredMixin. шаблон и поведение такие же, как для аутентификации входа в систему, хотя, конечно, вы можете разумно добавить несколько разрешений.

+ +

Функция в представлении с декоратором:

+ +
from django.contrib.auth.decorators import permission_required
+
+@permission_required('catalog.can_mark_returned')
+@permission_required('catalog.can_edit')
+def my_view(request):
+    ...
+ +

Требуется разрешение mixin для представлений на основе классов.

+ +
from django.contrib.auth.mixins import PermissionRequiredMixin
+
+class MyView(PermissionRequiredMixin, View):
+    permission_required = 'catalog.can_mark_returned'
+    # Or multiple permissions
+    permission_required = ('catalog.can_mark_returned', 'catalog.can_edit')
+    # Note that 'catalog.can_edit' is just an example
+    # the catalog application doesn't have such permission!
+ +

Пример

+ +

Мы не будем обновлять LocalLibrary здесь; возможно, в следующем уроке!

+ +

Испытайте себя

+ +

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

+ +

 Вы должны следовать той же схеме, что и для другого представления. Главное отличие состоит в том, что вам нужно ограничить представление только библиотекарями. Вы можете сделать это на основе того, является ли пользователь сотрудником (декоратор функции:  staff_member_required, переменная шаблона: user.is_staff) но мы рекомендуем вам вместо этого использовать  can_mark_returned разрешения и PermissionRequiredMixin, как описано в предыдущем разделе.

+ +
+

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

+
+ +

 Когда вы закончите, ваша страница должна выглядеть примерно, как на скриншоте ниже.

+ +

All borrowed books, restricted to librarian

+ + + +

Подводим итоги

+ +

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

+ +

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

+ +

Смотрите также

+ + + +

{{PreviousMenuNext("Learn/Server-side/Django/Sessions", "Learn/Server-side/Django/Forms", "Learn/Server-side/Django")}}

diff --git a/files/ru/learn/server-side/django/deployment/index.html b/files/ru/learn/server-side/django/deployment/index.html new file mode 100644 index 0000000000..640527b63d --- /dev/null +++ b/files/ru/learn/server-side/django/deployment/index.html @@ -0,0 +1,680 @@ +--- +title: 'Django Руководство часть 11: Разворачивание сайта на сервере' +slug: Learn/Server-side/Django/Разворачивание +tags: + - Веб-сервер + - Для начинающих + - Разворачивание на сервере + - Развёртывание Django +translation_of: Learn/Server-side/Django/Deployment +--- +
{{LearnSidebar}}
+ +
{{PreviousMenuNext("Learn/Server-side/Django/Testing", "Learn/Server-side/Django/web_application_security", "Learn/Server-side/Django")}}
+ +

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

+ + + + + + + + + + + + +
Требования:Завершить изучение всех предыдущих частей руководства, включая Django Руководство часть 10:  Тестирование веб-приложений в Django.
Цель:Изучить, где и как вы можете развернуть приложение Django для публичного доступа.
+ +

Обзор

+ +

Даже когда разработка вашего сайта завершена (или "достаточно" завершена для начала публичного тестирования), то для публичного доступа вам надо его где-то разместить.

+ +

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

+ + + +

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

+ +

Что такое окружение развертывания?

+ +

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

+ + + +
+

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

+
+ +

Сервер может быть вашим собственным с подключением к интернету по скоростному каналу, но более общим подходом является применение "облачных решений". Что действительно имеет значение, так это то, что ваш код запускается на некотором удаленном компьютере (возможно и "виртуальном"), в хостинговом дата-центре. Удаленный сервер обычно предоставляет определенный доступ к компьютерным ресурсам (процессору, оперативной памяти, памяти на жестких носителях и так далее) и соединение с интернетом за некоторую цену.

+ +

Такой тип удаленного доступа к вычислительному/сетевому железу называется Инфраструктура как Сервис (Infrastructure as a Service - IaaS). Множество IaaS поставщиков предлагают услуги по предустановке какой-либо операционной системы, на которую вы можете установить необходимые для вашего рабочего окружения компоненты. Другие поставщики предлагают вам выбрать уже готовые полноценные рабочие окружения, возможно, включающие в себя Django и настроенный веб-сервер.

+ +
+

Примечание: Готовые окружения могут сделать настройку вашего веб-сайта очень простой задачей, поскольку они имеют минимальную конфигурацию, однако, либо количество доступных опций может быть недостаточным, или они будут соответствовать устаревшей операционной системе. Часто, более предпочтительно установить необходимые компоненты самостоятельно, таким образом вы получите то, что вам необходимо, а в последующем, при обновлении системы, уже будете знать что нужно делать!

+
+ +

Некоторые провайдеры поддерживают Django как часть своего предложения Платформа как Сервис (Platform as a Service - PaaS). При данном виде хостинга вам не нужно беспокоиться о большей части окружения (веб-сервере, сервере приложений, балансировщике загрузки), так как сама платформа берет это на себя (включая все моменты, касающиеся роста и развития вашего приложения). В данном случае развертывание приложения является достаточно простой задачей, - вам нужно сконцентрироваться только на вашем приложении, а не на инфраструктуре.

+ +

Некоторые разработчики выбирают более гибкое решение, предоставляемое IaaS, в то время как другие предпочитают иметь наименьшие накладные расходы и простое масштабирование, предоставляемое PaaS. Когда вы только начинаете, то система типа PaaS является предпочтительной и это именно то, что мы будем использовать в данном руководстве.

+ +
+

Примечание: Если вы выбираете хостинг с поддержкой Python/Django, то он должен иметь инструкцию по установке веб-сайта Django, учитывающую различные конфигурации веб-сервера, сервера приложений, обратного прокси и так далее (это не имеет значение, если вы выбрали PaaS). Например, существует множество инструкций "шаг-за-шагом" для различный конфигураций в Документации DigitalOcean по Django.

+
+ +

Выбор хостинг провайдера

+ +

Существует более 100 хорошо известных хостинг провайдеров, которые либо активно поддерживают, или работают с Django (их список можно увидеть в Django-дружественные хостинги). Данные поставщики предоставляют различные типы окружений (IaaS, PaaS), и различные уровни доступа к вычислительным и сетевым ресурсам, за разную цену.

+ +

Некоторые вещи на которые надо обратить внимание при выборе хостинга:

+ + + +

Хорошей новостью является то, что для того, чтобы начать существует достаточное количество компаний, которые предоставляют пробные "бесплатные" тарифы типа "evaluation" (для пробы), "developer" (разработка), или "hobbyist" (хобби). Всегда существуют ресурсы с ограниченым окружением, при использовании которых вам надо беспокоиться лишь о том, что они могут быть доступны лишь в течении определенного периода времени. Тем не менее, они являются отличным решением для тестирования сайтов с небольшим трафиком в реальном окружении, а также могут предоставлять простой доступ к платным ресурсам, в случае необходимости. Наиболее популярными провайдерами являются Heroku, Python Anywhere, Amazon Web Services, Microsoft Azure и так далее.

+ +

Многие провайдеры имеют "basic" (базовый) тариф, предоставляющий достаточный уровень вычислительной мощности с небольшим количеством ограничений. Digital Ocean и Python Anywhere являются примерами провайдеров, которые предлагают относительно недорой базовый тариф (от $5 до $10USD в месяц).

+ +
+

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

+
+ +

Подготовка веб-сайта к публикации

+ +

Скелет сайта был создан при помощи инструментов django-admin и manage.py, которые настроены таким образом, чтобы сделать разработку проще. Многие настройки файла проекта (определенных в settings.py) должны быть изменены перед публикацией сайта, либо из-за вопросов безопастности, либо производительности.

+ +
+

Примечание: Общепринятым решением является иметь отдельный файл settings.py для публикации, который импортирует важные настройки из внешних файлов, или из переменных окружения. Доступ к данному файлу должен быть ограничен, даже если остальная часть исходного кода доступна в публичном репозитории.

+
+ +

Критически важные настройки файла settings.py:

+ + + +

Давайте изменим приложение LocalLibrary таким образом, чтобы читать SECRET_KEY и DEBUG из переменных окружения, если те определены, иначе использовать значения по умолчанию.

+ +

Откройте /locallibrary/settings.py, закомментируйте исходное значение SECRET_KEY и добавьте новые строки, как указано ниже жирным. В течении разработки, никаких переменных окружения определено не было, таким образом будут использоваться значения по умолчанию (не имеет значения какой ключ вы используете в процессе разработки, поскольку при развертывании проекта вы будете использовать другой).

+ +
# SECURITY WARNING: keep the secret key used in production secret!
+# SECRET_KEY = 'cg#p$g+j9tax!#a3cup@1$8obt2_+&k3q+pmu)5%asj6yjpkag'
+import os
+SECRET_KEY = os.environ.get('DJANGO_SECRET_KEY', 'cg#p$g+j9tax!#a3cup@1$8obt2_+&k3q+pmu)5%asj6yjpkag')
+
+ +

Затем закомментируйте строку с настройкой DEBUG, а затем, добавьте новую, указанную ниже.

+ +
# SECURITY WARNING: don't run with debug turned on in production!
+# DEBUG = True
+DEBUG = bool( os.environ.get('DJANGO_DEBUG', True) )
+
+ +

Значение DEBUG будет True по умолчанию и станет False, в том случае, если переменная окружения DJANGO_DEBUG будет проинициализирована пустой строкой, то есть, DJANGO_DEBUG=''.

+ +
+

Примечание: Было бы более понятным, если бы мы могли просто установить и снять с  DJANGO_DEBUG непосредственно на True и False , напрямую, а не использовать «любую строку» или «пустую строку» (соответственно). К сожалению, значения переменных среды хранятся как строки Python и единственная строка, которая оценивается как False является пустой строкой (например, bool('')==False).

+
+ +

Весь перечень настроек для разворачивания вашего сайта находится по ссылке Deployment checklist (Django docs). Кроме того, вы можете получить список настроек, выполнив в терминале команду:

+ +
python3 manage.py check --deploy
+
+ +

Пример: Установка LocalLibrary на Heroku

+ +

Данный раздел предоставляет демонстрацию того, как установить LocalLibrary на Heroku PaaS cloud.

+ +

Почему Heroku?

+ +

Heroku - один из самых продолжительных и популярных облачных сервисов PaaS. Первоначально он поддерживал только приложения Ruby, но теперь его можно использовать для размещения приложений из многих сред программирования, включая Django!

+ +

Мы выбираем для использования Heroku по нескольким причинам:

+ + + +

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

+ +

Как работает Heroku?

+ +

Heroku запускает сайты Django внутри одного, или более,  изолированых друг от друга "Dynos", которые являются виртуальными Unix-контейнерами, предоставляющими необходимое окружение для вашего приложения. Данные dynos полностью изолированы и имеют эфемерную файловую систему ("короткоживущая" файловая система, которая полностью очищается и обновляется каждый раз, когда dyno перезапускается). Единственной сущностью, которую предоставляет dynos по умолчанию, является приложение по конфигурации переменных. Heroku внутри себя применяет балансировщик загрузки для распределения веб-трафика среди всех "веб"-dynos. Поскольку dynos изолированы, Heroku может масштабировать приложение горизонтально, просто добавляя больше dynos (хотя, конечно, у вас может появиться необходимость расширить базу данных для обработки дополнительных соединений).

+ +

Файловая система эфемерна, поэтому вы не можете напрямую установить необходимые для вашего приложения сервисы (то есть, базы данных, очереди, системы кэширования, хранения, сервисы электронной почты и так далее). Взамен этого, Heroku предоставляет сервисы, доступные как независимые "дополнения" ("add-ons") либо от самой Heroku, или от сторонних разработчиков. В тот момент когда ваше приложение запускается в системе, dynos получает доступ к сервисам, используя информацию, содержащуюся в переменных настройки вашего приложения.

+ +

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

+ + + +

Разработчики Developers взаимодействуют с Heroku при помощи специального клиентского приложения/терминала, который сильно похож на bash-скрипт Unix. Оно позволяет вам загружать код, находящийся в git-репозитории, контроллировать выполняемые процессы, смотреть логи, устанавливать конфигурационные переменные и многое другое!

+ +

Для того, чтобы заставить ваше приложение работать с Heroku, нам нужно разместить наше веб-приложение в git-репозитории, добавить, перечисленные ранее, файлы, подключить дополнение (add-on) базы данных и выполнить настройки для правильной работы со статическими файлами.

+ +

Когда мы выполним все, что необходимо для нашего сайта мы можем создать аккаунт Heroku, получить доступ к клиенту Heroku и использовать его, для установки нашего веб-сайта.

+ +
+

Примечание: Инструкции, перечисленные ниже, соответствуют процессу работы с Heroku во время написания данной статьи (английской версии - прим. перев.). Если Heroku значительно изменит этот процесс, вы можете воспользоваться соответствующим описанием: Heroku начало работы с Django.

+
+ +

На этом завершается краткий обзор начала работы с Heroku (более подробное руководство Как работает Heroku).

+ +

Создание репозитория приложения на Github

+ +

Heroku тесно интегрирована с системой управления версиями исходного кода git, используя ее для загрузки / синхронизации любых изменений, которые вы вносите в живую систему. Он делает это, добавляя новый «удаленный» репозиторий heroku с именем heroku, указывающий на репозиторий для вашего источника в облаке Heroku. Во время разработки вы используете git для хранения изменений в вашем «master» репозитории. Когда вы хотите развернуть свой сайт, вы синхронизируете свои изменения в репозитории Heroku.

+ +
+

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

+
+ +

Существует множество способов работы с git, но одним из самых простых является создание учетной записи в Github, создание репозитория там, а затем синхронизация с ним локально:

+ +
    +
  1. Посетите https://github.com/ и создайте аккаунт.
  2. +
  3. После входа в систему нажмите ссылку + в верхней панели инструментов и выберите Новый репозиторий.
  4. +
  5. Заполните все поля на этой форме. Хотя они не являются обязательными, они настоятельно рекомендуются. +
      +
    • Введите имя нового репозитория (например django_local_library), и комментарий к репозиторию (например "Local Library website written in Django".
    • +
    • Нажмите на кнопку Add .gitignore и в появившемся списке выберите Python.
    • +
    • Выберите подходящую вам лицензию из списка Add license. Если не знаете для чего это - оставьте как было.
    • +
    • +

      Установите галочку напротив Initialize this repository with a README.

      +
    • +
    +
  6. +
  7. Нажмите кнопку Create repository, тем самым создав ваш репозиторий.
  8. +
  9. Перейдите на страницу вашего репозитория. Там нажмите на зелёную кнопку "Clone or download". Скопируйте URL  из текстового поляиз появившегося диалогового окна (Это будет похоже на: https://github.com/<your_git_user_id>/django_local_library.git). Здесь <your_git_user_id> - это будет ваш id пользователя git.
  10. +
+ +

Когда ваш репозиторий будет создан - загрузите его себе на компьтер, следуя инструкции, описанной ниже:

+ +
    +
  1. Установите git себе на компьютер (Вы можете найти версию для своей платформы здесь).
  2. +
  3. Откройте командную строку (или терминал) и выполните в нём следующую команду, используя ссылку, которую вы получили с github: +
    git clone https://github.com/<your_git_user_id>/django_local_library.git
    +
    + Это создаст подпапку (с содержанием вашего репозитория и именем вашего репозитория) внутри папки, в котрой выполнялась команда.
  4. +
  5. Перейдите в эту папку: +
    cd django_local_library.git
    +
  6. +
+ +

Последний шаг. Нужно скопировать ваше Django-приложение и добавить его файлы в новый репозиторий, используя git:

+ +
    +
  1. Скопируйте ваше приложение в папку репозитория (все файлы с таким же уровнем, как у manage.py, БЕЗ папки проекта, в которой эти файлы находятся).
  2. +
  3. Откройте файл с расширением .gitignore в текстовом редакторе, вставьте в самый его конец строки, приведённые ниже, а затем сохраните (этот файл "говорит" о файлах, которые не должны быть  загружены в git по умолчанию). +
    # Text backup files
    +*.bak
    +
    +#Database
    +*.sqlite3
    +
  4. +
  5. +

    Откройте командную строку или терминал и используйте add команду с флагом -A. Эта комманда сохранит изменения в репозиторий:

    + +
    git add -A
    +
  6. +
  7. Используйте команду status,  что бы убедиться, что все файлы, которые вы собираетесь добавить верны (вы хотите включить исходные файлы, а не бинарные файлы, временные файлы и т. д.). В консоль выведется что то вроде этого: +
    > git status
    +On branch master
    +Your branch is up-to-date with 'origin/master'.
    +Changes to be committed:
    +  (use "git reset HEAD <file>..." to unstage)
    +
    +        modified:   .gitignore
    +        new file:   catalog/__init__.py
    +        ...
    +        new file:   catalog/migrations/0001_initial.py
    +        ...
    +        new file:   templates/registration/password_reset_form.html
    +
  8. +
  9. Теперь, зафиксируйте файлы в локальном репозитории: +
    git commit -m "First version of application moved into github"
    +
  10. +
  11. Синхронизируете свой локальный репозиторий с сайтом Github: +
    git push origin master
    +
  12. +
+ +

Когда эти операции завершатся, вернитесь на страницу Github где вы создали свой репозиторий, обновите страницу, и убедитесь, что ваше приложение полностью загружено. При надобности обновить файлы на репозитории - повторите цикл ввода команд add/commit/push.

+ +
+

Подсказка: Это хороший момент для создания резервной копии вашего «ванильного» проекта — в то время как некоторые изменения, которые мы собираемся сделать в следующих разделах, могут быть полезны для развертывания на любой платформе (или разработке), которые другие могут не использовать.

+ +

Лучший способ сделать это - использовать git для управления вашими изменениями. С git вы можете не только вернуться к определенной старой версии, но и сохранить ее в отдельной «ветке» ваших производственных изменений, and cherry-pick - выбрать любые изменения для перемещения между ветвями производства и развития. Изучение Git будет стоить усилий, но это выходит за рамки данной темы. Самый простой способ сделать это - просто скопировать файлы в другое место. Используйте тот подход, который наилучшим образом соответствует вашим знаниям git!

+
+ +

Обновить приложение для Heroku 

+ +

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

+ +

Procfile

+ +

 Создайте файл с именем Procfile (без расширения) в корне нашего GitHub репозитории объявить типы процессов и точки входа приложения. Скопируйте в него следующий текст:

+ +
web: gunicorn locallibrary.wsgi --log-file -
+ +

«web:» сообщает Heroku, что это веб динамический и может быть отправлен HTTP-трафик. Процесс, который начнется в этом динамически, - это gunicorn, который является популярным сервером веб-приложений, который рекомендует Heroku. Мы запускаем Gunicorn, используя конфигурационную информацию в модуле locallibrary.wsgi (созданный с помощью нашего скелета приложения: /locallibrary/wsgi.py).

+ +

Gunicorn

+ +

Gunicorn рекомендуемый http сервер с Django на Heroku (Как указанов Procfile выше). Это чистый python http сервер для WSGI приложений  которые могут запускать множество параллельных python процессов в пределах одного динамического (посмотрите Deploying Python applications with Gunicorn для получения большей информации).

+ +

Также нам не понадобится Gunicorn для обслушивания нашей LocalLibrary приложения в течение разработки, мы установим это так, чтобы он стал частью наших требований к Heroku для настройки на удаленном сервере.

+ +

Установка Gunicorn локально в командной строке используя пакетный менеджер pip (которые мы установили когда настраивали среду разработки):

+ +
pip3 install gunicorn
+
+ +

Настройка Базы Данных

+ +

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

+ +

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

+ +

Информация о подключении базы данных предоставляется на web dyno, используя конфигурационную переменную с именем DATABASE_URL. Вместо того, чтобы жестко кодировать эту информацию в Django, Heroku рекомендует разработчикам использовать dj-database-url пакет для анализа DATABASE_URL переменную окружения и автоматически преобразовать ее в желаемый формат конфигурации Django. В дополнение к установке пакета dj-database-url нам также потребуется установить psycopg2, поскольку Django нуждается в этом, чтобы взаимодействовать с базами данных Postgres.

+ +
dj-database-url (Django конфигурации базы данных из переменной окружения)
+ +

Установите dj-database-url локально, чтобы он стал частью наших требований к настройке Heroku на удаленном сервере:

+ +
$ pip3 install dj-database-url
+
+ +
settings.py
+ +

Откройте /locallibrary/settings.py и скопируйте следующую конфигурацию в нижнюю часть файла:

+ +
# Heroku: Update database configuration from $DATABASE_URL.
+import dj_database_url
+db_from_env = dj_database_url.config(conn_max_age=500)
+DATABASES['default'].update(db_from_env)
+ +
+

Заметка:

+ + +
+ +
psycopg2 (Python Postgres database support)
+ +

Django нуждается в psycopg2 для работы с базами данных Postgres, и вам нужно будет добавить это в файл требований.txt для Heroku, чтобы установить это на удаленном сервере (как описано в разделе требований ниже).

+ +

Django будет использовать нашу базу данных SQLite локально по умолчанию, поскольку переменная среды DATABASE_URL не задана в нашей локальной среде. Если вы хотите полностью перейти на Postgres и использовать нашу бесплатную базу данных Heroku для разработки и производства, то вы можете. Например, чтобы установить psycopg2 и его зависимости локально в системе на базе Linux, вы должны использовать следующие команды bash / terminal:

+ +
sudo apt-get install python-pip python-dev libpq-dev postgresql postgresql-contrib
+pip3 install psycopg2
+
+ +

Инструкции по установке для других платформ можно найти на веб-сайте psycopg2.

+ +

Однако вам не нужно это делать - вам не нужно, чтобы PostGreSQL был активным на локальном компьютере, если вы передаете его в Heroku в качестве требования в файле требований.txt (см. Ниже).

+ +

Обслуживание статических файлов в производстве

+ +


+ Во время разработки мы использовали Django и веб-сервер разработки Django для обслуживания наших статических файлов (CSS, JavaScript и т. Д.). В производственной среде вместо этого мы обычно обслуживаем статические файлы из сети доставки контента (CDN) или веб-сервера.

+ +
+

Примечание. Обслуживание статических файлов через Django / веб-приложение неэффективно, потому что запросы должны проходить через ненужный дополнительный код (Django), а не обрабатываться непосредственно веб-сервером или полностью отдельным CDN. Хотя это не имеет значения для местного использования во время разработки, это будет иметь значительное влияние на производительность, если мы будем использовать тот же подход в производстве.

+
+ +

Чтобы упростить размещение статических файлов отдельно от веб-приложения Django, Django предоставляет средство сбора данных для сбора этих файлов для развертывания (имеется переменная параметров, определяющая, где файлы должны собираться при запуске collectstatic). Шаблоны Django относятся к месту размещения статических файлов относительно переменной параметров (STATIC_URL), так что это можно изменить, если статические файлы перемещаются на другой хост / сервер.

+ +

Соответствующими параметрами настройки являются:

+ +

     STATIC_URL: это базовое расположение URL, из которого будут загружены статические файлы, например, на CDN. Это используется для переменной статического шаблона, доступ к которой осуществляется в нашем базовом шаблоне (см. Учебник по Django Part 5: Создание нашей домашней страницы).
+       STATIC_ROOT: Это абсолютный путь к каталогу, в котором инструмент «collectstatic» Django будет собирать любые статические файлы, упомянутые в наших шаблонах. После их сбора они затем могут быть загружены в группу, где бы файлы не размещались.
+       STATICFILES_DIRS: В этом списке перечислены дополнительные каталоги, в которых инструмент коллективного поиска Django должен искать статические файлы.

+ +
settings.py
+ +

Откройте /locallibrary/settings.py и скопируйте следующую конфигурацию в нижнюю часть файла. BASE_DIR уже должен быть определен в вашем файле (STATIC_URL, возможно, уже был определен в файле, когда он был создан. В то время как это не причинит вреда, вы также можете удалить дублируемую предыдущую ссылку).

+ +
# Static files (CSS, JavaScript, Images)
+# https://docs.djangoproject.com/en/1.10/howto/static-files/
+
+# The absolute path to the directory where collectstatic will collect static files for deployment.
+STATIC_ROOT = os.path.join(BASE_DIR, 'staticfiles')
+
+# The URL to use when referring to static files (where they will be served from)
+STATIC_URL = '/static/'
+
+ +

Фактически мы будем делать файл, используя библиотеку WhiteNoise, которую мы устанавливаем и настраиваем в следующем разделе.

+ +

Для получения дополнительной информации см. Django и Static Assets (документы Heroku).

+ +

WhiteNoise
+ Существует множество способов обслуживания статических файлов на производстве (мы видели соответствующие настройки Django в предыдущих разделах). Heroku рекомендует использовать проект WhiteNoise для обслуживания статических активов непосредственно из Gunicorn в производстве.

+ +
+

Заметка: Heroku автоматически вызывает collectstatic и готовит ваши статические файлы для использования WhiteNoise после того, как он загрузит ваше приложение. Посмотрите WhiteNoise документацию для объяснения того, как она работает, и почему реализация является относительно эффективным методом для обслуживания этих файлов.

+
+ +

Шаги по настройке WhiteNoise для использования в проекте:

+ +
WhiteNoise
+ +

Установите WhiteNoise локально, используя следующую команду:

+ +
$ pip3 install whitenoise
+
+ +
settings.py
+ +

Чтобы установить WhiteNoise в приложение Django, откройте /locallibrary/settings.py, найдите параметр MIDDLEWARE и добавьте WhiteNoiseMiddleware в верхней части списка, чуть ниже SecurityMiddleware:

+ +
MIDDLEWARE = [
+    'django.middleware.security.SecurityMiddleware',
+    'whitenoise.middleware.WhiteNoiseMiddleware',
+    'django.contrib.sessions.middleware.SessionMiddleware',
+    'django.middleware.common.CommonMiddleware',
+    'django.middleware.csrf.CsrfViewMiddleware',
+    'django.contrib.auth.middleware.AuthenticationMiddleware',
+    'django.contrib.messages.middleware.MessageMiddleware',
+    'django.middleware.clickjacking.XFrameOptionsMiddleware',
+]
+
+ +

При желании вы можете уменьшить размер статических файлов при их обслуживании (это более эффективно). Просто добавьте следующее в конец /locallibrary/settings.py:

+ +
# Simplified static file serving.
+# https://warehouse.python.org/project/whitenoise/
+STATICFILES_STORAGE = 'whitenoise.storage.CompressedManifestStaticFilesStorage'
+
+ +

Requirements

+ +

Требования Python вашего веб-приложения должны храниться в файле requirements.txt в корневом каталоге вашего репозитория. После этого Heroku автоматически установит их при восстановлении вашей среды. Вы можете создать этот файл с помощью pip в командной строке (запустите в корне repo):

+ +
pip3 freeze > requirements.txt
+ +

После установки всех разных зависимостей выше, файл requirements.txt должен иметь по меньшей мере эти перечисленные элементы (хотя номера версий могут отличаться). Удалите любые другие зависимости, не перечисленные ниже, если вы явно не добавили их для этого приложения.

+ +
dj-database-url==0.4.1
+Django==1.10.2
+gunicorn==19.6.0
+psycopg2==2.6.2
+whitenoise==3.2.2
+
+ +
+

Убедитесь, что строка  psycopg2, подобная приведенной выше, присутствует! Даже если вы не установили это локально, вы должны добавить это в requirements.txt.

+
+ +

Среда выполнения

+ +

Файл runtime.txt, если определён, говорит Heroku, какой язык программирования использовать. Создайте файл в корне репо и добавьте следующий текст:

+ +
python-3.5.2
+ +
+

Заметка: Heroku поддерживает только небольшое количество Python runtimes. (на момент написания статьи, в том числе и выше). Heroku будет использовать поддерживаемую среду выполнения независимо от значения, указанного в этом файле.

+
+ +

Сохраните изменения в Github и перепроверьте

+ +

Далее мы сохраним все наши изменения в Github. В терминале (whist внутри нашего репозитория) введите следующие команды:

+ +
git add -A
+git commit -m "Added files and changes required for deployment to heroku"
+git push origin master
+ +

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

+ +
python3 manage.py runserver
+ +

Теперь мы должны быть готовы начать развертывание LocalLibrary на Heroku.

+ +

Получить аккаунт в heroku

+ +

Чтобы начать использовать Heroku, вам сначала нужно создать учетную запись:

+ + + +

Установка клиента

+ +

Загрузите и установите клиент Heroku, следуя инструкциям Heroku здесь.

+ +

После установки клиента вам будут дотупны команды. Например, чтобы получить справку о клиенте:

+ +
heroku help
+
+ +

Создание и загрузка веб-сайта

+ +

Чтобы создать приложение, мы запускаем команду «create» в корневом каталоге нашего репозитория. Это создает git remote («указатель на удаленный репозиторий»), названный heroku в нашей локальной среде git.

+ +
heroku create
+ +
+

Заметка: Вы можете назвать удаленный, если хотите, указав значение после «create». Если вы этого не сделаете, вы получите случайное имя. Имя используется в URL-адресе по умолчанию.

+
+ +

Затем мы можем подтолкнуть наше приложение в репозиторий heroku как показано ниже. Это позволит загрузить приложение, упаковать его в dyno, запустить collectstatic, и запустить сам сайт.

+ +
git push heroku master
+ +

Если нам повезет, приложение «заработает» на сайте, но оно не будет работать должным образом, потому что мы не настроили таблицы базы данных для использования нашим приложением. Для этого нам нужно использовать команду  heroku run и запустить "one off dyno" для выполнения операции переноса. Введите в терминал следующую команду:

+ +
heroku run python manage.py migrate
+ +

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

+ +
heroku run python manage.py createsuperuser
+ +

Как только это будет завершено, мы можем посмотреть сайт. Он должен работать, хотя в нем еще нет книг. Чтобы открыть браузер на новом веб-сайте, используйте команду:

+ +
heroku open
+ +

Создайте несколько книг на сайте администратора и проверьте, работает ли сайт, как вы ожидаете.

+ +

Управление аддонами

+ +

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

+ +
>heroku addons
+
+Add-on                                     Plan       Price  State
+─────────────────────────────────────────  ─────────  ─────  ───────
+heroku-postgresql (postgresql-flat-26536)  hobby-dev  free   created
+ └─ as DATABASE
+ +

Здесь мы видим, что у нас есть только одна надстройка, база данных postgres SQL. Это бесплатно и автоматически создается при создании приложения. Вы можете открыть веб-страницу, чтобы более подробно изучить надстройку базы данных (или любое другое дополнение), используя следующую команду:

+ +
heroku addons:open heroku-postgresql
+
+ +

Другие команды позволяют создавать, уничтожать, обновлять и понижать аддоны (используя аналогичный синтаксис для открытия). Для получения дополнительной информации см.  Managing Add-ons (Heroku docs).

+ +

Настройка переменных конфигурации

+ +

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

+ +
>heroku config
+
+=== locallibrary Config Vars
+DATABASE_URL: postgres://uzfnbcyxidzgrl:j2jkUFDF6OGGqxkgg7Hk3ilbZI@ec2-54-243-201-144.compute-1.amazonaws.com:5432/dbftm4qgh3kda3
+ +

Если вы вспомните из раздела, посвященного  getting the website ready to publish, мы должны установить переменные среды для DJANGO_SECRET_KEY и DJANGO_DEBUG. Давайте сделаем это сейчас.

+ +
+

Заметка: Секретный ключ должен быть действительно секретным! Один из способов генерации нового ключа - создать новый проект Django (django-admin startproject someprojectname) а затем получить ключ, который генерируется для вас в его settings.py.

+
+ +

Мы устанавливаем  DJANGO_SECRET_KEY используя команду config:set (как показано ниже). Не забудьте использовать свой секретный ключ!

+ +
>heroku config:set DJANGO_SECRET_KEY=eu09(ilk6@4sfdofb=b_2ht@vad*$ehh9-)3u_83+y%(+phh&=
+
+Setting DJANGO_SECRET_KEY and restarting locallibrary... done, v7
+DJANGO_SECRET_KEY: eu09(ilk6@4sfdofb=b_2ht@vad*$ehh9-)3u_83+y%(+phh
+
+ +

Аналогично мы устанавливаем  DJANGO_DEBUG:

+ +
>heroku config:set DJANGO_DEBUG=''
+
+Setting DJANGO_DEBUG and restarting locallibrary... done, v8
+ +

Если вы посетите веб-сайт сейчас, вы получите ошибку "Bad request" , потому что в  ALLOWED_HOSTS надо внести параметры, если у вас DEBUG=False (в качестве меры безопасности). Откройте /locallibrary/settings.py и измените ALLOWED_HOSTS для включения вашего базового URL-адреса приложения (например, 'locallibrary1234.herokuapp.com') URL, который вы обычно используете на локальном сервере разработки.

+ +
ALLOWED_HOSTS = ['<your app URL without the https:// prefix>.herokuapp.com','127.0.0.1']
+# For example:
+# ALLOWED_HOSTS = ['fathomless-scrubland-30645.herokuapp.com','127.0.0.1']
+
+ +

Затем сохраните настройки и передайте их в репозиторий Github и в Heroku:

+ +
git add -A
+git commit -m 'Update ALLOWED_HOSTS with site and development server URL'
+git push origin master
+git push heroku master
+ +
+

После завершения обновления сайта на Heroku введите URL-адрес, который не существует (например,  /catalog/doesnotexist/). Раньше это отображало бы подробную страницу отладки, но теперь вы должны просто увидеть простую страницу «Не найдено».

+
+ +

Отладка

+ +

Клиент Heroku предоставляет несколько инструментов для отладки:

+ +
heroku logs  # Show current logs
+heroku logs --tail # Show current logs and keep updating with any new results
+heroku config:set DEBUG_COLLECTSTATIC=1 # Add additional logging for collectstatic (this tool is run automatically during a build)
+heroku ps   #Display dyno status
+
+ +

Если вам нужно больше информации, предоставленной здесь, вам нужно будет начать изучать Django Logging.

+ + + +

Итоги

+ +

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

+ +

Смотрите также

+ + + +

{{PreviousMenuNext("Learn/Server-side/Django/Testing", "Learn/Server-side/Django/web_application_security", "Learn/Server-side/Django")}}

+ +

В этом модуле

+ + diff --git a/files/ru/learn/server-side/django/introduction/index.html b/files/ru/learn/server-side/django/introduction/index.html new file mode 100644 index 0000000000..4bff707908 --- /dev/null +++ b/files/ru/learn/server-side/django/introduction/index.html @@ -0,0 +1,257 @@ +--- +title: Django введение +slug: Learn/Server-side/Django/Введение +tags: + - Python + - django + - Вступление + - Джанго + - Начинающим + - Серверное программирование +translation_of: Learn/Server-side/Django/Introduction +--- +
{{LearnSidebar}}
+ +
{{NextMenu("Learn/Server-side/Django/development_environment", "Learn/Server-side/Django")}}
+ +

В первой статье о Django мы отвечаем на вопрос «Что такое Django?» и даём обзор того, что делает его особенным. Мы опишем основные функции, в том числе некоторые из расширенных функций, которые у нас не будет времени подробно рассмотреть в этом модуле. Мы также покажем вам некоторые основные строительные блоки приложения Django (хотя на данный момент у вас ещё не будет среды разработки для тестирования).

+ + + + + + + + + + + + +
Требования:Базовая компьютерная грамотность. Общее понимание server-side website programming, и в частности, механики client-server interactions in websites.
Задача:Узнать, что такое Django, какие функции он предоставляет, и основные строительные блоки приложения Django.
+ +

Что такое Django?

+ +

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

+ +

Django помогает писать программное обеспечение, которое будет:

+ +
+
Полным
+
Django следует философии «Всё включено» и предоставляет почти всё, что разработчики могут захотеть сделать «из коробки». Поскольку всё, что вам нужно, является частью единого «продукта», всё это безупречно работает вместе, соответствует последовательным принципам проектирования и имеет обширную и актуальную документацию.
+
Разносторонним
+
Django может быть (и был) использован для создания практически любого типа веб-сайтов — от систем управления контентом и wiki до социальных сетей и новостных сайтов. Он может работать с любой клиентской средой и может доставлять контент практически в любом формате (включая HTML, RSS-каналы, JSON, XML и т. д.). Сайт, который вы сейчас читаете, создан с помощью Django!
+
Хотя Django предоставляет решения практически для любой функциональности, которая вам может понадобиться (например, для нескольких популярных баз данных, шаблонизаторов и т. д.), внутренне он также может быть расширен сторонними компонентами, если это необходимо.
+
Безопасным
+
Django помогает разработчикам избежать многих распространённых ошибок безопасности, предоставляя фреймворк, разработанный чтобы «делать правильные вещи» для автоматической защиты сайта. Например, Django предоставляет безопасный способ управления учётными записями пользователей и паролями, избегая распространённых ошибок, таких как размещение информации о сеансе в файлы cookie, где она уязвима (вместо этого файлы cookie содержат только ключ, а фактические данные хранятся в базе данных) или непосредственное хранение паролей вместо хэша пароля.
+
Хэш пароля это значение фиксированной длины, созданное путём обработки пароля через криптографическую хэш-функцию. Django может проверить правильность введённого пароля, пропустив его через хэш-функцию и сравнив вывод с сохранённым значением хэша. Благодаря «одностороннему» характеру функции, даже если сохранённое хэш-значение скомпрометировано, злоумышленнику будет сложно определить исходный пароль.
+
Django, по умолчанию, обеспечивает защиту от многих уязвимостей, включая SQL-инъекцию, межсайтовый скриптинг, подделку межсайтовых запросов и кликджекинг (см. Website security для получения дополнительной информации об этих атаках).
+
Масштабируемым
+
Django использует компонентную “shared-nothing” архитектуру (каждая её часть  независима от других и, следовательно, может быть заменена или изменена, если это необходимо). Чёткое разделение частей означает, что Django может масштабироваться при увеличении трафика, путём добавления оборудования на любом уровне: серверы кэширования, серверы баз данных или серверы приложений. Одни из самых загруженных сайтов успешно масштабировали Django (например, Instagram и Disqus, если назвать только два из них).
+
Удобным в сопровождении
+
Код Django написан с использованием принципов и шаблонов проектирования, которые поощряют создание поддерживаемого и повторно используемого кода. В частности, в нём используется принцип «Don't Repeat Yourself» (DRY, «не повторяйся»), поэтому нет ненужного дублирования, что сокращает объём кода. Django также способствует группированию связанных функциональных возможностей в повторно используемые «приложения» и, на более низком уровне, группирует связанный код в модули (в соответствии с шаблоном Model View Controller (MVC)).
+
Переносным
+
Django написан на Python, который работает на многих платформах. Это означает, что вы не привязаны к какой-либо конкретной серверной платформе и можете запускать приложения на многих версиях Linux, Windows и Mac OS X. Кроме того, Django хорошо поддерживается многими веб-хостингами, которые часто предоставляют определённую инфраструктуру и документацию для размещения сайтов Django.
+
+ +

Как он появился?

+ +

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

+ +

Django продолжает расти и улучшаться с момента его первого релиза (1.0) в сентябре 2008 года до недавно выпущенной версии 3.1 (2020). В каждой версии добавлены новые функциональные возможности и исправлены ошибки, начиная от поддержки новых типов баз данных, шаблонизаторов и кэширования, до добавления «общих» функций просмотра и классов (уменьшающих объём кода, который разработчики должны писать для ряда программных задач).

+ +
+

Заметка: Ознакомтесь с примечаниями к версии на сайте Django, чтобы увидеть что изменилось в последних версиях и как много работы было проделано, чтобы улучшить Django.

+
+ +

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

+ +

Насколько популярен Django?

+ +

Нет никаких доступных и окончательных оценок популярности серверных фреймворков (хотя сайты наподобие Hot Framework и пытаются оценить популярность, используя такие механизмы, как подсчёт количества проектов на GitHub и вопросов на StackOverflow для каждой платформы). Лучший вопрос — «достаточно ли Django популярен», чтобы избежать проблем непопулярных платформ. Продолжает ли он развиваться? Можете ли вы получить помощь, если вам нужно? Найдёте ли вы оплачиваемую работу, если изучите Django?

+ +

Основываясь на количестве крупных сайтов, которые используют Django, количестве участников и количестве людей, предоставляющих как бесплатную, так и платную поддержку, можно ответить: да, Django — популярный фреймворк!

+ +

Django используют такие крупные сайты, как Disqus, Instagram, Knight Foundation, MacArthur Foundation, Mozilla, National Geographic, Open Knowledge Foundation, Pinterest и Open Stack (источник: обзорная страница Django).

+ +

Является ли Django гибким?

+ +

Веб-фрейморки часто можно поделить на "гибкие" и "негибкие".

+ +

Негибкие - это те, у которых есть "правильный путь" для решения какой-либо конкретной задачи. Они часто поддерживают быстрое развёртывание в определенной области (решение проблем определенного типа), потому что правильный способ сделать что-либо обычно хорошо понимается и хорошо документируется. Однако они могут быть менее гибкими при решении проблем за пределами их основной сферы и, как правило, предлагают меньше вариантов того, какие компоненты и подходы они могут использовать.

+ +

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

+ +

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

+ +

Как выглядит код Django?

+ +

На традиционном информационом веб-сайте веб-приложение ожидает HTTP-запросы от веб-браузера (или другого клиента). Когда запрос получен, приложение разрабатывает то, что необходимо на основе URL-адреса и, возможно, данных в POST или GET запросах. В зависимости от того, что требуется, далее он может читать или записывать информацию из базы данных или выполнять другие задачи, необходимые для удовлетворения запроса. Затем приложение вернёт ответ веб-браузеру, часто динамически создавая HTML-страницу для отображения в браузере, вставляя полученные данные в HTML-шаблон.

+ +

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

+ +

+ + + +
+

Заметка: Django реализует уровневую архитектуру "Model View Template (MVT)". Она имеет много общего с более известной архитектурой Model View Controller

+
+ + + +

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

+ +

Отправка запроса в правильное view (urls.py)

+ +

Сопоставитель URL-адресов обычно содержится в файле urls.py. В примере ниже сопоставитель (urlpatterns) определяет список сопоставлений междумаршрутами (определёнными URL-шаблонами) и соотвествующими функциями отображения (view). Если получен HTTP-запрос, который имеет URL-адрес, соответствующий определённому шаблону, то затем будет вызвана связанная функция отображения (view) и передана в запрос.

+ +
urlpatterns = [
+    path('admin/', admin.site.urls),
+    path('book/<int:id>/', views.book_detail, name='book_detail'),
+    path('catalog/', include('catalog.urls')),
+    re_path(r'^([0-9]+)/$', views.best),
+]
+ +

Объект urlpatterns является списком функций path() и/или re_path() (в Python списки определяются с помощью квадратных скобок, внутри которых элементы разделены запятыми и могут содержать необязательную завершающую запятую. Например: [item1, item2, item3,]).

+ +

Первый аргумент в обоих методах - маршрут (шаблон), который будет сопоставлен. В методе path() угловые скобки используются для определения частей URL-адреса, которые будут захвачены и переданы в функцию отображения (view) в качестве именованных аргументов. Функция re_path() использует гибкий подход к сопоставлению с шаблоном, известный как регулярное выражение. Мы поговорим об этом в следующей статье!

+ +

Второй аргумент — это ещё одна функция, которая будет вызываться при сопоставлении шаблона. Обозначение views.book_detail указывает, что функция называется book_detail() и может быть обнаружена в модуле с именем views (т.е. внутри файла с именем views.py).

+ +

Обработка запроса (views.py)

+ +

Отображения (views) — это сердце веб-приложения, принимающего HTTP-запросы от веб-клиентов и возвращающего HTTP-ответы. Между этим они используют другие ресурсы фреймворка для доступа к базам данных, шаблонам визуализации и т. д.  

+ +

В приведённом ниже примере показана минимальная функция представления index(), которая могла быть вызвана нашим сопоставителем URL-адресов в предыдущем разделе. Как и все функции отображения (view), она получает объект HttpRequest в качестве параметра (request) и возвращает объект HttpResponse. В этом случае мы ничего не делаем с запросом, и наш ответ просто возвращает жёстко запрограммированную строку. Мы покажем вам запрос, который делает что-то более интересное в следующем разделе.

+ +
## filename: views.py (Django view functions)
+
+from django.http import HttpResponse
+
+def index(request):
+    # Получить HttpRequest — параметр запроса
+    # Выполнить операции, используя информацию из запроса.
+    # Вернуть HttpResponse
+    return HttpResponse('Hello from Django!')
+
+ +
+

Заметка: Немного Python:

+ + +
+ + + +

Отображения (view) обычно содержатся в файле views.py.

+ +

Определение данных модели (models.py)

+ +

Веб-приложения Django обрабатывают и запрашивают данные через объекты Python, называемые моделями. Модели определяют структуру хранимых данных, включая типы полей и, возможно, их максимальный размер, значения по умолчанию, параметры списка выбора, текст справки для документации, текст меток для форм и т. д. Определение модели не зависит от используемой базы данных — ваши модели будут работать в любой из них. После того как вы выбрали базу данных, которую хотите использовать, вам не нужно напрямую обращатся к ней — вы просто пишете свою структуру модели и другой код, а Django выполняет всю «грязную работу» по обращению к базе данных за вас.

+ +

В приведённом ниже фрагменте кода показана очень простая модель Django для объекта Team. Класс Team наследуется от класса models.Model. Он определяет имя команды и командный уровень в качестве полей символов и задаёт максимальное количество символов, которые могут быть сохранены для каждой записи. Team_level может быть одним из нескольких значений, поэтому мы определяем его как поле выбора и предоставляем сопоставление между отображаемыми вариантами и хранимыми данными вместе со значением по умолчанию.

+ +
# filename: models.py
+
+from django.db import models
+
+class Team(models.Model):
+    team_name = models.CharField(max_length=40)
+
+    TEAM_LEVELS = (
+        ('U09', 'Under 09s'),
+        ('U10', 'Under 10s'),
+        ('U11', 'Under 11s'),
+        ...  #список других командных уровней
+    )
+    team_level = models.CharField(max_length=3,choices=TEAM_LEVELS,default='U11')
+
+ +
+

Заметка: Немного Python:

+ + +
+ +

Запросы данных (views.py)

+ +

Модель Django предоставляет простой API запросов для поиска в базе данных. Поиск может осуществляться по нескольким полям одновременно, используя различные критерии (такие как exact («точный»), case-insensitive («без учёта регистра»), greater than («больше чем») и т. д.), и может поддерживать сложные выражения (например, вы можете указать поиск в командах U11, у которых есть имя команды, начинающееся с «Fr» или заканчивается на «al»).

+ +

Фрагмент кода показывает функцию view (обработчик ресурсов) для отображения всех команд U09. Выделенная жирным строка показывет, как мы можем использовать модель API-запросов для того, чтобы отфильтровать все записи, где поле team_level в точности содержит текст 'U09' (обратите внимание, как эти критерии передаются функции filter() в качестве аргумента с именем поля и типом соответствия, разделённым двойным подчеркиванием: team_level__exact). 

+ +
## filename: views.py
+
+from django.shortcuts import render
+from .models import Team
+
+def index(request):
+    list_teams = Team.objects.filter(team_level__exact="U09")
+    context = {'youngest_teams': list_teams}
+    return render(request, '/best/index.html', context)
+
+ +
+
+ +

Данная функция использует функцию render() для того, чтобы создать HttpResponse, который будет отправлен назад браузеру. Эта функция является ярлыком; она создаёт HTML-файл, комбинируя указанный HTML-шаблон и некоторые данные для вставки в шаблон (предоставляется в переменной с именем «context»). В следующем разделе мы  покажем как данные вставляются в шаблон для создания HTML-кода.

+ +

Вывод данных (HTML-шаблоны)

+ +

Системы шаблонов позволяют указать структуру выходного документа, используя заполнители для данных, которые будут вставлены при генерировании страницы. Шаблоны часто используются для создания HTML, но также могут создавать другие типы документов. Django «из коробки» поддерживает как собственную систему шаблонов, так и другую популярную библиотеку Python под названием Jinja2 (она также может быть использована для поддержки других систем, если это необходимо).

+ +

Фрагмент кода показывает, как может выглядеть HTML-шаблон, вызванный функцией  render() из предыдущего раздела. Этот шаблон был написан с предположением, что во время отрисовки он будет иметь доступ к переменной списка, названной youngest_teams (содержащейся в контекстной переменной внутри функции render() выше). Внутри скелета HTML мы имеем выражение, которое сначала проверяет, существует ли переменная youngest_teams, а затем повторяет её в цикле for. При каждом повторе шаблон отображает значение team_name каждой команды в элементе {{htmlelement("li")}}.

+ +
## filename: best/templates/best/index.html
+
+<!DOCTYPE html>
+<html lang="en">
+<head>
+  <meta charset="utf-8">
+  <title>Home page</title>
+</head>
+<body>
+  {% if youngest_teams %}
+    <ul>
+      {% for team in youngest_teams %}
+        <li>\{\{ team.team_name \}\}</li>
+      {% endfor %}
+    </ul>
+  {% else %}
+    <p>No teams are available.</p>
+  {% endif %}
+</body>
+</html>
+ +

Что ещё можно сделать?

+ +

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

+ + + +

Резюме

+ +

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

+ +

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

+ +
{{NextMenu("Learn/Server-side/Django/development_environment", "Learn/Server-side/Django")}}
diff --git a/files/ru/learn/server-side/django/sessions/index.html b/files/ru/learn/server-side/django/sessions/index.html new file mode 100644 index 0000000000..5f7d492c72 --- /dev/null +++ b/files/ru/learn/server-side/django/sessions/index.html @@ -0,0 +1,181 @@ +--- +title: 'Руководство часть 7: Сессии' +slug: Learn/Server-side/Django/Сессии +tags: + - django + - Джанго + - Для начинающих + - Изучение + - Питон + - Руководство + - Серверная сторона + - Статья + - применение сессий + - сессии +translation_of: Learn/Server-side/Django/Sessions +--- +
{{LearnSidebar}}
+ +
{{PreviousMenuNext("Learn/Server-side/Django/Generic_views", "Learn/Server-side/Django/authentication_and_sessions", "Learn/Server-side/Django")}}
+ +

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

+ + + + + + + + + + + + +
Требования:Завершить изучение всех предыдущих разделов, включая Django Руководство Часть 6: Обобщенные отображения списков и детальной информации
Цель:Понимать как применять сессии.
+ +

Обзор

+ +

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

+ +

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

+ +

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

+ +

Что такое сессии?

+ +

Все взаимодействия между браузерами и серверами осуществляются при помощи протокола HTTP, который не сохраняет свое состояние (stateless). Данный факт означает, что сообщения между клиентом и сервером являются полностью независимыми один от другого — то есть не существует какого-либо представления "последовательности", или поведения в зависимости от предыдущих сообщений. В результате, если вы хотите создать сайт который будет отслеживать взаимодействие с клиентом (браузером), вам нужно реализовать это самостоятельно.

+ +

Сессии являются механизмом, который использует Django (да и весь остальной "Интернет") для отслеживания "состояния" между сайтом и каким-либо браузером. Сессии позволяют вам хранить произвольные данные браузера и получать их в тот момент, когда между данным браузером и сайтом устанавливается соединение. Данные получаются и сохраняются в сессии при помощи соответствующего "ключа".

+ +

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

+ +

Подключение сессий

+ +

Сессии стали доступны автоматически в тот момент, когда мы создали скелет сайта (во второй части руководства).

+ +

Необходимые конфигурации выполняются в разделах INSTALLED_APPS и MIDDLEWARE файла проекта (locallibrary/locallibrary/settings.py), как показано ниже:

+ +
INSTALLED_APPS = [
+    ...
+    'django.contrib.sessions',
+    ....
+
+MIDDLEWARE = [
+    ...
+    'django.contrib.sessions.middleware.SessionMiddleware',
+    ....
+ +

Применение сессий

+ +

Вы можете получить доступ к переменной session, в соответствующем отображении, через параметр request (HttpRequest передается как первый аргумент в каждое отображение). Переменная сессии является связью с определенным пользователем (или, если быть более точным, связью с определенным браузером, который определяется при помощи идентификатора (id) сессии, получаемого из куки браузера).

+ +

Переменная (или поле) session является объектом-словарем, который служит для чтения и записи неограниченное число раз. С ним вы можете выполнять любые стандартные операции, включая очистку всех данных, проверку наличия ключа, циклы по данным и так далее. Большую часть времени вы будете тратить на  обычные "словарные" операции - получения и установки значений.

+ +

Ниже представлены фрагменты кода, которые показывают вам как получать, задавать и удалять некоторые данные при помощи ключа "my_car", связанного с текущей сессией (браузером). 

+ +
+

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

+
+ +
# Получение значения сессии при помощи ключа(то есть, 'my_car').
+# Если такого ключа нет, то возникнет ошибка KeyError
+my_car = request.session['my_car']
+
+# Получение значения сессии. Если значения не существует,
+# то вернется значение по умолчанию ('mini')
+my_car = request.session.get('my_car', 'mini')
+
+# Передача значения в сессию
+request.session['my_car'] = 'mini'
+
+# Удаление значения из сессии
+del request.session['my_car']
+
+ +

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

+ +

Хранение данных сессии

+ +

По умолчанию Django сохраняет данные сессии в базу данных и отправляет соответствующие куки клиенту только тогда, когда сессия была изменена, или удалена. Если вы обновляете какие-либо данные при помощи ключа сессии, как показано в предыдущем фрагменте, тогда вам не надо беспокоиться о процессе сохранения! Например:

+ +
# Данное присваивание распознается как обновление сессии
+# и данные будут сохранены
+request.session['my_car'] = 'mini'
+ +

Если вы обновлете информацию внутри данных сессии, тогда Django не распознает эти изменения и не выполнит сохранение данных (например, если вы изменили "wheels" внутри переменной "my_car", как показано ниже). В таких случаях вам надо явно указывать, что сессия была изменена.

+ +
# Объект сессии модифицируется неявно.
+# Изменения НЕ БУДУТ сохранены!
+request.session['my_car']['wheels'] = 'alloy'
+
+# Явное указание, что данные изменены.
+# Сессия будет сохранена, куки обновлены (если необходимо).
+request.session.modified = True
+
+ +
+

Примечание: Вы можете изменить поведение сессий таким образом, чтобы они записывали любое свое изменение в базу данных и отправляли куки, при каждом запросе, путем установки SESSION_SAVE_EVERY_REQUEST = True, в файле настроек проекта (locallibrary/locallibrary/settings.py).

+
+ +

Простой пример — получение числа визитов

+ +

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

+ +

Откройте /locallibrary/catalog/views.py и добавьте изменения, выделенных жирным, ниже. 

+ +
def index(request):
+    ...
+
+    num_authors=Author.objects.count()  # The 'all()' is implied by default.
+
+    # Number of visits to this view, as counted in the session variable.
+    num_visits=request.session.get('num_visits', 0)
+    request.session['num_visits'] = num_visits+1
+
+    # Render the HTML template index.html with the data in the context variable.
+    return render(
+        request,
+        'index.html',
+        context={'num_books':num_books,'num_instances':num_instances,'num_instances_available':num_instances_available,'num_authors':num_authors,
+            'num_visits':num_visits}, # num_visits appended
+    )
+ +

В первую очередь мы получаем значение 'num_visits' из сессии, возвращая 0, если оно не было установлено ранее. Каждый раз при получении запроса, мы увеличиваем данное значение на единицу и сохраняем его обратно в сессии (до следующего посещения данной страницы пользователем). Затем переменная num_visits передается в шаблон через переменную контекста context.  

+ +
+

Примечание: Можно проверить наличие поддержки куки в браузере (для примера, смотрите Как использовать сессии), или разработать наш UI таким образом, чтобы это не имело значения.

+
+ +

Для показа значения переменной, из следующего фрагмента добавьте нижнюю строчку кода в ваш шаблон главной страницы сайта (/locallibrary/catalog/templates/index.html), в его нижний раздел "Dynamic content":

+ +
<h2>Dynamic content</h2>
+
+<p>The library has the following record counts:</p>
+<ul>
+<li><strong>Books:</strong> \{{ num_books }}</li>
+<li><strong>Copies:</strong> \{{ num_instances }}</li>
+<li><strong>Copies available:</strong> \{{ num_instances_available }}</li>
+<li><strong>Authors:</strong> \{{ num_authors }}</li>
+</ul>
+
+<p>You have visited this page \{{ num_visits }}{% if num_visits == 1 %} time{% else %} times{% endif %}.</p>
+
+ +

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

+ + + +

Итоги

+ +

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

+ +

В наших следующих статьях мы рассмотрим фреймворк аутентификации и авторизации (разрешение доступа, permission), и покажем вам как поддерживать пользовательские аккаунты.

+ +

Смотрите также

+ + + +

{{PreviousMenuNext("Learn/Server-side/Django/Generic_views", "Learn/Server-side/Django/Authentication", "Learn/Server-side/Django")}}

diff --git "a/files/ru/learn/server-side/django/\320\260\321\203\321\202\320\265\320\275\321\202\320\270\321\204\320\270\320\272\320\260\321\206\320\270\321\217/index.html" "b/files/ru/learn/server-side/django/\320\260\321\203\321\202\320\265\320\275\321\202\320\270\321\204\320\270\320\272\320\260\321\206\320\270\321\217/index.html" deleted file mode 100644 index 807db42a90..0000000000 --- "a/files/ru/learn/server-side/django/\320\260\321\203\321\202\320\265\320\275\321\202\320\270\321\204\320\270\320\272\320\260\321\206\320\270\321\217/index.html" +++ /dev/null @@ -1,688 +0,0 @@ ---- -title: 'Руководство Django Часть 8: Аутентификация и авторизация пользователя' -slug: Learn/Server-side/Django/Аутентификация -tags: - - Python - - Аутентификация - - Аутентификация django - - Джанго - - Начинающий - - Обучение - - Разграничение доступа - - Руководство - - Сервер - - Статья - - Формы - - на стороне сервера - - сессии -translation_of: Learn/Server-side/Django/Authentication ---- -
{{LearnSidebar}}
- -
{{PreviousMenuNext("Learn/Server-side/Django/Sessions", "Learn/Server-side/Django/Forms", "Learn/Server-side/Django")}}
- -

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

- - - - - - - - - - - - -
Требования:Завершить изучение предыдущих тем руководства, включая Руководство Django Часть 7: Работа с сессиями.
Цель:Понимать как настроить и использовать механизм аутентификации пользователя и разграничений прав доступа.
- -

Обзор

- -

Django предоставляет систему аутентификации и авторизации ("permission") пользователя, реализованную на основе фреймворка работы с сессиями, который мы рассматривали в предыдущей части. Система аутентификации и авторизации позволяет вам проверять учетные данные пользователей и определять какие действия какой пользователь может выполнять. Данный фреймворк включает в себя встроенные модели для Пользователей и Групп (основной способ применения прав доступа для более чем одного пользователя), непосредственно саму систему прав доступа (permissions)/флаги, которые определяют может ли пользователь выполнить задачу, с какой формой и отображением для авторизованых пользователей, а так же получить доступ к контенту с ограниченым доступом.

- -
-

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

-
- -

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

- -

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

- -

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

- -

Подключение аутентификации

- -

Аутентификация была подключена автоматически когда мы создали скелет сайта (в части 2), таким образом на данный момент вам ничего не надо делать.

- -
-

Примечание: Необходимые настройки были выполнены для нас, когда мы создали приложение при помощи команды django-admin startproject. Таблицы базы данных для пользователей и модели авторизации были созданы, когда в первый раз выполнили команду python manage.py migrate.

-
- -

Соответствующие настройки сделаны в параметрах INSTALLED_APPS и MIDDLEWARE файла проекта (locallibrary/locallibrary/settings.py), как показано ниже:

- -
INSTALLED_APPS = [
-    ...
-    'django.contrib.auth',  # Фреймворк аутентификации и моделей по умолчанию.
-    'django.contrib.contenttypes',  # Django контент-типовая система (даёт разрешения, связанные с моделями).
-    ....
-
-MIDDLEWARE = [
-    ...
-    'django.contrib.sessions.middleware.SessionMiddleware',  # Управление сессиями между запросами
-    ...
-    'django.contrib.auth.middleware.AuthenticationMiddleware',  # Связывает пользователей, использующих сессии, запросами.
-    ....
-
- -

Создание пользователей и групп

- -

Вы уже создали своего первого пользователя когда мы рассматривали Административная панель сайта Django в части 4 (это был суперпользователь, созданный при помощи команды python manage.py createsuperuser). Наш суперпользователь уже авторизован и имеет все необходимые уровни доступа к данным и функциям, таким образом нам необходимо создать тестового пользователя для отработки соответствующей работы сайта. В качестве наиболее быстрого способа, мы будем использовать административную панель сайта для создания соответствующих групп и акканутов locallibrary.

- -
-

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

- -
from django.contrib.auth.models import User
-
-# Создайте пользователя и сохраните его в базе данных
-user = User.objects.create_user('myusername', 'myemail@crazymail.com', 'mypassword')
-
-# Обновите поля и сохраните их снова
-user.first_name = 'John'
-user.last_name = 'Citizen'
-user.save()
-
-
- -

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

- -

Запустите сервер разработки и перейдите к административной панели вашего сайта (http://127.0.0.1:8000/admin/). Залогиньтесь на сайте при помощи параметров (имя пользователя и пароля) аккаунта суперпользователя. Самая "верхняя" страница панели Администратора показывает все наши модели. Для того, чтобы увидеть записи в разделе Authentication and Authorisation вы можете нажать на ссылку Users, или Groups.

- -

Admin site - add groups or users

- -

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

- -
    -
  1. Нажмите на кнопку Add (Добавить) (рядом с Group) и создайте новую группу; для данной группы введите Name (Имя) "Library Members".Admin site - add group
  2. -
  3. Для данной группы не нужны какие-либо разрешения, поэтому мы просто нажимаем кнопку SAVE (Сохранить) (вы перейдете к списку групп).
  4. -
- -

Теперь давайте создадим пользователя:

- -
    -
  1. Перейдите обратно на домашнюю страницу административной панели
  2. -
  3. Для перехода к диалогу добавления пользователя нажмите на кнопку Add, соответствующую строке Users (Пользователи).Admin site - add user pt1
  4. -
  5. Введите соответствующие Username (имя пользователя) и Password/Password confirmation (пароль/подтверждение пароля) для вашего тестового пользователя
  6. -
  7. Нажмите SAVE для завершения процесса создания пользователя.
    -
    - Административная часть сайта создаст нового пользователя и немедленно перенаправит вас на страницу Change user (Изменение параметров пользователя) где вы можете, соответственно, изменить ваш username, а кроме того добавить информацию для дополнительных полей модели User. Эти поля включают в себя имя пользователя, фамилию, адрес электронной почты, статус пользователя, а также соответствующие параметры доступа (может быть установлен только флаг  Active). Ниже вы можете определить группу для пользователя и необходимые параметры доступа, а кроме того, вы можете увидеть важные даты, относящиеся к пользователю (дату подключения к сайту и дату последнего входа).Admin site - add user pt2
  8. -
  9. В разделе Groups, из списка Доступные группы выберите группу Library Member, а затем переместите ее в блок "Выбранные группы" (нажмите стрелку-"направо", находящуюся между блоками).Admin site - add user to group
  10. -
  11. Больше нам не нужно здесь нечего делать, просто нажмите "Save"(Сохранить), и вы вернетесь к списку созданых пользователей.
  12. -
- -

Вот и все! Теперь у вас есть учетная запись «обычного члена библиотеки», которую вы сможете использовать для тестирования (как только добавим страницы, чтобы пользователи могли войти в систему).

- -
-

Note: Попробуйте создать другого пользователя, например "Библиотекаря". Так же создайте группу "Библиотекарей" и добавьте туда своего только что созданного библиотекаря

-
- -

Настройка представлений проверки

- -

Django предоставляет почти все, что нужно для создания страниц аутентификации входа, выхода из системы и управления паролями из коробки. Это включает в себя url-адреса, представления (views) и формы,но не включает шаблоны — мы должны создать свой собственный шаблон!

- -

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

- -
-

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

-
- -
-

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

-
- -

Проектирование URLs

- -

Добавьте следующее в нижней части проекта urls.py файл (locallibrary/locallibrary/urls.py) файл:

- -
#Add Django site authentication urls (for login, logout, password management)
-urlpatterns += [
-    path('accounts/', include('django.contrib.auth.urls')),
-]
-
- -

Перейдите по http://127.0.0.1:8000/accounts/ URL (обратите внимание на косую черту!), Django покажет ошибку, что он не смог найти этот URL, и перечислить все URL, которые он пытался открыть. Из этого Вы можете увидеть URL-адреса, которые будут работать, например:

- -
-

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

-
- -
-
accounts/ login/ [name='login']
-accounts/ logout/ [name='logout']
-accounts/ password_change/ [name='password_change']
-accounts/ password_change/done/ [name='password_change_done']
-accounts/ password_reset/ [name='password_reset']
-accounts/ password_reset/done/ [name='password_reset_done']
-accounts/ reset/<uidb64>/<token>/ [name='password_reset_confirm']
-accounts/ reset/done/ [name='password_reset_complete']
-
- -

Теперь попробуйте перейти к URL-адресу входа (http://127.0.0.1:8000/accounts/login/). Это приведет к сбою снова, но с ошибкой, сообщающей вам, что нам не хватает требуемого шаблона (registration / login.html) в пути поиска шаблона. Вы увидите следующие строки, перечисленные в желтом разделе вверху:

- -
Exception Type:    TemplateDoesNotExist
-Exception Value:    registration/login.html
- -

Следующий шаг - создать каталог регистрации в пути поиска, а затем добавить файл login.html.

- -

Каталог шаблонов

- -

URL-адреса (и неявные представления), которые мы только что добавили, ожидают найти связанные с ними шаблоны в каталоге / регистрации / где-то в пути поиска шаблонов.
-
- Для этого сайта мы разместим наши HTML-страницы в каталоге templates / registration /. Этот каталог должен находиться в корневом каталоге проекта, то есть в том же каталоге, что и в каталоге и папках locallibrary). Создайте эти папки сейчас.

- -
-

Примечание: Ваша структура папок теперь должна выглядеть как показано внизу:
- locallibrary (django project folder)
-    |_catalog
-    |_locallibrary
-    |_templates (new)
-                 |_registration

-
- -

Чтобы сделать эти директории видимыми для загрузчика шаблонов   (т. е. помещать этот каталог в путь поиска шаблона) откройте настройки проекта (/locallibrary/locallibrary/settings.py), и обновите в секции TEMPLATES строку 'DIRS' как показано.

- -
TEMPLATES = [
-    {
-        ...
-        'DIRS': [os.path.join(BASE_DIR, 'templates')],
-        'APP_DIRS': True,
-        ...
-
- -

Шаблон аутентификации

- -
-

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

-
- -

Создайте новый HTML файл, названный /locallibrary/templates/registration/login.html. дайте ему следующее содержание:

- -
{% extends "base_generic.html" %}
-
-{% block content %}
-
-{% if form.errors %}
-  <p>Your username and password didn't match. Please try again.</p>
-{% endif %}
-
-{% if next %}
-  {% if user.is_authenticated %}
-    <p>Your account doesn't have access to this page. To proceed,
-    please login with an account that has access.</p>
-  {% else %}
-    <p>Please login to see this page.</p>
-  {% endif %}
-{% endif %}
-
-<form method="post" action="{% url 'login' %}">
-{% csrf_token %}
-<table>
-
-<tr>
-  <td>\{{ form.username.label_tag }}</td>
-  <td>\{{ form.username }}</td>
-</tr>
-
-<tr>
-  <td>\{{ form.password.label_tag }}</td>
-  <td>\{{ form.password }}</td>
-</tr>
-</table>
-
-<input type="submit" value="login" />
-<input type="hidden" name="next" value="\{{ next }}" />
-</form>
-
-{# Assumes you setup the password_reset view in your URLconf #}
-<p><a href="{% url 'password_reset' %}">Lost password?</a></p>
-
-{% endblock %}
- -

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

- -

Перейдите на страницу входа (http://127.0.0.1:8000/accounts/login/) когда вы сохраните свой шаблон, и вы должны увидеть что-то наподобие этого:

- -

Library login page v1

- -

Если ваша попытка войти в систему будет успешной,  вы будете перенаправлены на другую страницу (по умолчанию это будет http://127.0.0.1:8000/accounts/profile/). Проблема здесь в том, что по умолчанию Django ожидает, что после входа в систему вы захотите перейти на страницу профиля, что может быть или не быть. Поскольку вы еще не определили эту страницу, вы получите еще одну ошибку!
-
- Откройте настройки проекта (/locallibrary/locallibrary/settings.py) и добавьте текст ниже. Теперь, когда вы входите в систему, вы по умолчанию должны перенаправляться на домашнюю страницу сайта.

- -
# Redirect to home URL after login (Default redirects to /accounts/profile/)
-LOGIN_REDIRECT_URL = '/'
-
- -

Шаблон выхода

- -

Если вы перейдете по URL-адресу выхода (http://127.0.0.1:8000/accounts/logout/), то увидите странное поведение - ваш пользователь наверняка выйдет из системы, но вы попадете на страницу выхода администратора. Это не то, что вам нужно, хотя бы потому, что ссылка для входа на этой странице приведет вас к экрану входа в систему администратора. (и это доступно только для пользователей, у которых есть разрешение is_staff).
-
- Создайте и откройте /locallibrary/templates/registration/logged_out.html. Скопируйте текст ниже:

- -
{% extends "base_generic.html" %}
-
-{% block content %}
-<p>Logged out!</p>
-
-<a href="{% url 'login'%}">Click here to login again.</a>
-{% endblock %}
- -

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

- -

Library logout page v1

- -

Шаблон сброса пароля

- -

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

- -

Форма сброса пароля

- -

Это форма, используемая для получения адреса электронной почты пользователя (для отправки пароля для сброса пароля). Создайте /locallibrary/templates/registration/password_reset_form.html и дайте ему следующее содержание:

- -
{% extends "base_generic.html" %}
-{% block content %}
-
-<form action="" method="post">{% csrf_token %}
-    {% if form.email.errors %} \{{ form.email.errors }} {% endif %}
-        <p>\{{ form.email }}</p>
-    <input type="submit" class="btn btn-default btn-lg" value="Reset password" />
-</form>
-
-{% endblock %}
-
- -

Сброс пароля

- -

Эта форма отображается после того, как ваш адрес электронной почты будет собран. Создайте /locallibrary/templates/registration/password_reset_done.html, и дайте ему следующее содержание:

- -
{% extends "base_generic.html" %}
-{% block content %}
-<p>We've emailed you instructions for setting your password. If they haven't arrived in a few minutes, check your spam folder.</p>
-{% endblock %}
-
- -

Сброс пароля по email

- -

Этот шаблон предоставляет текст электронной почты HTML, содержащий ссылку на сброс, которую мы отправим пользователям. Создайте /locallibrary/templates/registration/password_reset_email.html и дайте ему следующее содержание:

- -
Someone asked for password reset for email \{{ email }}. Follow the link below:
-\{{ protocol}}://\{{ domain }}{% url 'password_reset_confirm' uidb64=uid token=token %}
-
- -

Подтверждение на сброс пароля

- -

На этой странице вы вводите новый пароль после нажатия ссылки в электронном письме с возвратом пароля. Создайте /locallibrary/templates/registration/password_reset_confirm.html и дайте ему следующее содержание:

- -
{% extends "base_generic.html" %}
-
-{% block content %}
-
-    {% if validlink %}
-        <p>Please enter (and confirm) your new password.</p>
-        <form action="" method="post">
-            {% csrf_token %}
-            <table>
-                <tr>
-                    <td>\{{ form.new_password1.errors }}
-                        <label for="id_new_password1">New password:</label></td>
-                    <td>\{{ form.new_password1 }}</td>
-                </tr>
-                <tr>
-                    <td>\{{ form.new_password2.errors }}
-                        <label for="id_new_password2">Confirm password:</label></td>
-                    <td>\{{ form.new_password2 }}</td>
-                </tr>
-                <tr>
-                    <td></td>
-                    <td><input type="submit" value="Change my password" /></td>
-                </tr>
-            </table>
-        </form>
-    {% else %}
-        <h1>Password reset failed</h1>
-        <p>The password reset link was invalid, possibly because it has already been used. Please request a new password reset.</p>
-    {% endif %}
-
-{% endblock %}
-
- -

Сброс пароля завершен

- -

Это последний шаблон сброса пароля, который отображается, чтобы уведомить вас о завершении сброса пароля. Создайте /locallibrary/templates/registration/password_reset_complete.html и дайте ему следующее содержание:

- -
{% extends "base_generic.html" %}
-{% block content %}
-
-<h1>The password has been changed!</h1>
-<p><a href="{% url 'login' %}">log in again?</a></p>
-
-{% endblock %}
- -

Тестирование новых страниц аутентификации

- -

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

- - - -

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

- -
-

Заметка: Система сброса пароля требует, чтобы ваш сайт поддерживал электронную почту, что выходит за рамки этой статьи, поэтому эта часть еще не будет работать. Чтобы разрешить тестирование, поместите следующую строку в конец файла settings.py. Это регистрирует любые письма, отправленные на консоль (чтобы вы могли скопировать ссылку на сброс пароля с консоли).

- -
EMAIL_BACKEND = 'django.core.mail.backends.console.EmailBackend'
-
- -

Для получения дополнительной информации см. Отправка email (Django docs).

-
- -

Тестирование проверки подлинности пользователей

- -

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

- -

Тестирование в шаблонах

- -

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

- -

Обычно вы сначала проверяете переменную шаблона \{{user.is_authenticated}}, чтобы определить, имеет ли пользователь право видеть конкретный контент. Чтобы продемонстрировать это, мы обновим нашу боковую панель, чтобы отобразить ссылку «Вход», если пользователь вышел из системы, и ссылку «Выход», если он вошёл в систему.

- -

Откройте базовый шаблон (/locallibrary/catalog/templates/base_generic.html) и скопируйте следующий текст в sidebar блок непосредственно перед тегом шаблона endblock.

- -
  <ul class="sidebar-nav">
-
-    ...
-
-   {% if user.is_authenticated %}
-     <li>User: \{{ user.get_username }}</li>
-     <li><a href="{% url 'logout'%}?next=\{{request.path}}">Logout</a></li>
-   {% else %}
-     <li><a href="{% url 'login'%}?next=\{{request.path}}">Login</a></li>
-   {% endif %} 
-  </ul>
- -

Как вы можете видеть, мы используем теги шаблона if-else-endif для условного отображения текста на основе того, является ли \{{user.is_authenticated}} истинным. Если пользователь аутентифицирован, мы знаем, что у нас есть действительный пользователь, поэтому мы вызываем \{{user.get_username}}, чтобы отобразить их имя.

- -

Мы создаем URL-адрес для входа и выхода из системы, используя тег шаблона URL-адреса и имена соответствующих конфигураций URLs. Также обратите внимание на то, как мы добавили ?next=\{{request.path}} в конец URLs. Это означает, что следующий URL-адрес содержит адрес (URL) текущей страницы, в конце связанного URL-адреса. После того, как пользователь успешно выполнил вход в систему, представления будут использовать значение "next" чтобы перенаправить пользователя обратно на страницу, где они сначала нажали ссылку входа / выхода из системы.

- -
-

Примечание: Попробуйте! Если вы находитесь на главной странице и вы нажимаете «Вход / Выход» на боковой панели, то после завершения операции вы должны вернуться на ту же страницу.

-
- -

Тестирование в представлениях

- -

Если вы используете функциональные представления, самым простым способом ограничить доступ к вашим функциям является применение login_required декоратор к вашей функции просмотра, как показано ниже. Если пользователь вошел в систему, ваш код просмотра будет выполняться как обычно. Если пользователь не вошел в систему, это перенаправит URL-адрес входа, определенный в настройках проекта. (settings.LOGIN_URL), передав текущий абсолютный путь в качестве next параметра URL. Если пользователю удастся войти в систему, они будут возвращены на эту страницу, но на этот раз аутентифицированы.

- -
from django.contrib.auth.decorators import login_required
-
-@login_required
-def my_view(request):
-    ...
- -
-

Заметка: Вы можете сделать то же самое вручную, путём тестирования request.user.is_authenticated, но декоратор намного удобнее!

-
- -

Аналогичным образом, самый простой способ ограничить доступ к зарегистрированным пользователям в ваших представлениях на основе классов - это производные от LoginRequiredMixin. Вы должны объявить этот mixin сначала в списке суперкласса, перед классом основного представления.

- -
from django.contrib.auth.mixins import LoginRequiredMixin
-
-class MyView(LoginRequiredMixin, View):
-    ...
- -

Это имеет такое же поведение при переадресации, что и  login_required декоратор. Вы также можете указать альтернативное местоположение для перенаправления пользователя, если он не аутентифицирован (login_url), и имя параметра URL вместо "next" , чтобы вставить текущий абсолютный путь (redirect_field_name).

- -
class MyView(LoginRequiredMixin, View):
-    login_url = '/login/'
-    redirect_field_name = 'redirect_to'
-
- -

Для получения дополнительной информации ознакомьтесь с  Django docs here.

- -

Пример - перечисление книг текущего пользователя

- -

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

- -

К сожалению, у нас пока нет возможности пользователям использовать книги! Поэтому, прежде чем мы сможем создать список книг, мы сначала расширим BookInstance модель для поддержки концепции заимствования и использования приложения Django Admin для заимствования ряда книг нашему тестовому пользователю.

- -

Модели

- -

Прежде всего, мы должны предоставить пользователям возможность кредита на BookInstance (у нас уже есть status и due_back дата, но у нас пока нет связи между этой моделью и пользователем. Мы создадим его с помощью поля ForeignKey (один ко многим). Нам также нужен простой механизм для проверки того, просрочена ли заемная книга.

- -

Откройте catalog/models.py, и импортируйте модель User из django.contrib.auth.models (добавьте это чуть ниже предыдущей строки импорта в верхней части файла, так User доступен для последующего кода, что позволяет использовать его):

- -
from django.contrib.auth.models import User
-
- -

Затем добавьте поле borrower в модель BookInstance:

- -
borrower = models.ForeignKey(User, on_delete=models.SET_NULL, null=True, blank=True)
-
- -

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

- -
from datetime import date
- -

Теперь добавьте следующее определение свойства внутри класса BookInstance:

- -
@property
-def is_overdue(self):
-    if self.due_back and date.today() > self.due_back:
-        return True
-    return False
- -
-

Примечание. Сначала мы проверим, является ли due_back пустым, прежде чем проводить сравнение. Пустое поле due_back заставило Django выкидывать ошибку, а не показывать страницу: пустые значения не сопоставимы. Это не то, что мы хотели бы, чтобы наши пользователи испытывали!

-
- -

Теперь, когда мы обновили наши модели, нам нужно будет внести новые изменения в проект, а затем применить эти миграции:

- -
python3 manage.py makemigrations
-python3 manage.py migrate
-
- -

Admin

- -

Теперь откройте каталог catalog/admin.py, и добавьте поле borrower в класс BookInstanceAdmin , как в list_display , так и в полях fieldsets , как показано ниже. Это сделает поле видимым в разделе Admin, так что мы можем при необходимости назначить User в BookInstance.

- -
@admin.register(BookInstance)
-class BookInstanceAdmin(admin.ModelAdmin):
-    list_display = ('book', 'status', 'borrower', 'due_back', 'id')
-    list_filter = ('status', 'due_back')
-
-    fieldsets = (
-        (None, {
-            'fields': ('book','imprint', 'id')
-        }),
-        ('Availability', {
-            'fields': ('status', 'due_back','borrower')
-        }),
-    )
- -

Займите несколько книг

- -

Теперь, когда возможно кредитовать книги конкретному пользователю, зайдите и заработайте на нескольких записей в BookInstance. Установите borrowed поле вашему тестовому пользователю, сделайте status «В займе» и установите сроки оплаты как в будущем, так и в прошлом.

- -
-

Заметка: Мы не будем описывать процесс, так как вы уже знаете, как использовать Admin сайт!

-
- -

Займ в представлении

- -

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

- -

Добавьте следующее в catalog/views.py:

- -
from django.contrib.auth.mixins import LoginRequiredMixin
-
-class LoanedBooksByUserListView(LoginRequiredMixin,generic.ListView):
-    """
-    Generic class-based view listing books on loan to current user.
-    """
-    model = BookInstance
-    template_name ='catalog/bookinstance_list_borrowed_user.html'
-    paginate_by = 10
-
-    def get_queryset(self):
-        return BookInstance.objects.filter(borrower=self.request.user).filter(status__exact='o').order_by('due_back')
- -

Чтобы ограничить наш запрос только объектами BookInstance для текущего пользователя, мы повторно реализуем get_queryset(), как показано выше. Обратите внимание, что "o" это сохраненный код для "on loan" и мы сортируем по дате due_back, чтобы сначала отображались самые старые элементы.

- -

URL-адрес для заёмных книг

- -

Теперь откройте /catalog/urls.py и добавьте url() , указывая на приведённое выше представление (вы можете просто скопировать текст ниже в конец файла).

- -
urlpatterns += [
-    url(r'^mybooks/$', views.LoanedBooksByUserListView.as_view(), name='my-borrowed'),
-]
- -

Шаблон для заёмных книг

- -

Теперь все, что нам нужно сделать для этой страницы, - это добавить шаблон. Сначала создайте файл шаблона /catalog/templates/catalog/bookinstance_list_borrowed_user.html и дайте ему следующее содержание:

- -
{% extends "base_generic.html" %}
-
-{% block content %}
-    <h1>Borrowed books</h1>
-
-    {% if bookinstance_list %}
-    <ul>
-
-      {% for bookinst in bookinstance_list %}
-      <li class="{% if bookinst.is_overdue %}text-danger{% endif %}">
-        <a href="{% url 'book-detail' bookinst.book.pk %}">\{{bookinst.book.title}}</a> (\{{ bookinst.due_back }})
-      </li>
-      {% endfor %}
-    </ul>
-
-    {% else %}
-      <p>There are no books borrowed.</p>
-    {% endif %}
-{% endblock %}
- -

Этот шаблон очень похож на тот, который мы создали ранее для объектов Book и Author. Единственное, что «новое» здесь, это то, что мы проверяем метод, который мы добавили в модель (bookinst.is_overdue) с целью использовать его для изменения цвета просроченных предметов.

- -

Когда сервер разработки запущен, вы должны теперь иметь возможность просматривать список для зарегистрированного пользователя в своем браузере по адресу  http://127.0.0.1:8000/catalog/mybooks/. Попробуйте это, когда ваш пользователь войдет в систему и выйдет из системы (во втором случае вы должны быть перенаправлены на страницу входа в систему).

- -

Добавить список на боковую панель

- -

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

- -

Откройте базовый шаблон (/locallibrary/catalog/templates/base_generic.html) и добавьте выделенную строку из sidebar, как показано на рисунке.

- -
 <ul class="sidebar-nav">
-   {% if user.is_authenticated %}
-   <li>User: \{{ user.get_username }}</li>
-   <li><a href="{% url 'my-borrowed' %}">My Borrowed</a></li>
-   <li><a href="{% url 'logout'%}?next=\{{request.path}}">Logout</a></li>
-   {% else %}
-   <li><a href="{% url 'login'%}?next=\{{request.path}}">Login</a></li>
-   {% endif %}
- </ul>
-
- -

На что это похоже?

- -

Когда любой пользователь войдет в систему, он будет видеть ссылку «Мной позаимствовано (My Borrowed)» в боковой колонке, и список книг, показанных ниже (первая книга не имеет установленной даты, что является ошибкой, которую мы надеемся исправить в более позднем уроке!).

- -

Library - borrowed books by user

- -

Права доступа

- -

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

- -

Модели

- -

Определение разрешений выполняется в разделе моделей "class Meta" , используется permissions поле. Вы можете указать столько разрешений, сколько необходимо в кортеже, причем каждое разрешение определяется во вложенном кортеже, содержащем имя разрешения и отображаемое значение разрешения. Например, мы можем определить разрешение, позволяющее пользователю отметить, что книга была возвращена, как показано здесь:

- -
class BookInstance(models.Model):
-    ...
-    class Meta:
-        ...
-        permissions = (("can_mark_returned", "Set book as returned"),)   
- -

Затем мы могли бы назначить разрешение группе «Библиотекарь» (Librarian) на сайте администратора.

- -

Откройте catalog/models.py, и добавьте разрешение, как показано выше. Вам нужно будет повторно выполнить миграцию (вызвав python3 manage.py makemigrations и python3 manage.py migrate) для надлежащего обновления базы данных.

- -

Шаблоны

- -

Разрешения текущего пользователя хранятся в переменной шаблона, называемой  \{{ perms }}. Вы можете проверить, имеет ли текущий пользователь определенное разрешение, используя конкретное имя переменной в соответствующем приложении «Django» - например, \{{ perms.catalog.can_mark_returned }} будет True если у пользователя есть это разрешение, а False - в противном случае. Обычно мы проверяем разрешение с использованием шаблона {% if %}, как показано в:

- -
{% if perms.catalog.can_mark_returned %}
-    <!-- We can mark a BookInstance as returned. -->
-    <!-- Perhaps add code to link to a "book return" view here. -->
-{% endif %}
-
- -

Представления

- -

Разрешения можно проверить в представлении функции, используя  permission_required декоратор или в представлении на основе классов, используя PermissionRequiredMixin. шаблон и поведение такие же, как для аутентификации входа в систему, хотя, конечно, вы можете разумно добавить несколько разрешений.

- -

Функция в представлении с декоратором:

- -
from django.contrib.auth.decorators import permission_required
-
-@permission_required('catalog.can_mark_returned')
-@permission_required('catalog.can_edit')
-def my_view(request):
-    ...
- -

Требуется разрешение mixin для представлений на основе классов.

- -
from django.contrib.auth.mixins import PermissionRequiredMixin
-
-class MyView(PermissionRequiredMixin, View):
-    permission_required = 'catalog.can_mark_returned'
-    # Or multiple permissions
-    permission_required = ('catalog.can_mark_returned', 'catalog.can_edit')
-    # Note that 'catalog.can_edit' is just an example
-    # the catalog application doesn't have such permission!
- -

Пример

- -

Мы не будем обновлять LocalLibrary здесь; возможно, в следующем уроке!

- -

Испытайте себя

- -

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

- -

 Вы должны следовать той же схеме, что и для другого представления. Главное отличие состоит в том, что вам нужно ограничить представление только библиотекарями. Вы можете сделать это на основе того, является ли пользователь сотрудником (декоратор функции:  staff_member_required, переменная шаблона: user.is_staff) но мы рекомендуем вам вместо этого использовать  can_mark_returned разрешения и PermissionRequiredMixin, как описано в предыдущем разделе.

- -
-

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

-
- -

 Когда вы закончите, ваша страница должна выглядеть примерно, как на скриншоте ниже.

- -

All borrowed books, restricted to librarian

- - - -

Подводим итоги

- -

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

- -

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

- -

Смотрите также

- - - -

{{PreviousMenuNext("Learn/Server-side/Django/Sessions", "Learn/Server-side/Django/Forms", "Learn/Server-side/Django")}}

diff --git "a/files/ru/learn/server-side/django/\320\262\320\262\320\265\320\264\320\265\320\275\320\270\320\265/index.html" "b/files/ru/learn/server-side/django/\320\262\320\262\320\265\320\264\320\265\320\275\320\270\320\265/index.html" deleted file mode 100644 index 4bff707908..0000000000 --- "a/files/ru/learn/server-side/django/\320\262\320\262\320\265\320\264\320\265\320\275\320\270\320\265/index.html" +++ /dev/null @@ -1,257 +0,0 @@ ---- -title: Django введение -slug: Learn/Server-side/Django/Введение -tags: - - Python - - django - - Вступление - - Джанго - - Начинающим - - Серверное программирование -translation_of: Learn/Server-side/Django/Introduction ---- -
{{LearnSidebar}}
- -
{{NextMenu("Learn/Server-side/Django/development_environment", "Learn/Server-side/Django")}}
- -

В первой статье о Django мы отвечаем на вопрос «Что такое Django?» и даём обзор того, что делает его особенным. Мы опишем основные функции, в том числе некоторые из расширенных функций, которые у нас не будет времени подробно рассмотреть в этом модуле. Мы также покажем вам некоторые основные строительные блоки приложения Django (хотя на данный момент у вас ещё не будет среды разработки для тестирования).

- - - - - - - - - - - - -
Требования:Базовая компьютерная грамотность. Общее понимание server-side website programming, и в частности, механики client-server interactions in websites.
Задача:Узнать, что такое Django, какие функции он предоставляет, и основные строительные блоки приложения Django.
- -

Что такое Django?

- -

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

- -

Django помогает писать программное обеспечение, которое будет:

- -
-
Полным
-
Django следует философии «Всё включено» и предоставляет почти всё, что разработчики могут захотеть сделать «из коробки». Поскольку всё, что вам нужно, является частью единого «продукта», всё это безупречно работает вместе, соответствует последовательным принципам проектирования и имеет обширную и актуальную документацию.
-
Разносторонним
-
Django может быть (и был) использован для создания практически любого типа веб-сайтов — от систем управления контентом и wiki до социальных сетей и новостных сайтов. Он может работать с любой клиентской средой и может доставлять контент практически в любом формате (включая HTML, RSS-каналы, JSON, XML и т. д.). Сайт, который вы сейчас читаете, создан с помощью Django!
-
Хотя Django предоставляет решения практически для любой функциональности, которая вам может понадобиться (например, для нескольких популярных баз данных, шаблонизаторов и т. д.), внутренне он также может быть расширен сторонними компонентами, если это необходимо.
-
Безопасным
-
Django помогает разработчикам избежать многих распространённых ошибок безопасности, предоставляя фреймворк, разработанный чтобы «делать правильные вещи» для автоматической защиты сайта. Например, Django предоставляет безопасный способ управления учётными записями пользователей и паролями, избегая распространённых ошибок, таких как размещение информации о сеансе в файлы cookie, где она уязвима (вместо этого файлы cookie содержат только ключ, а фактические данные хранятся в базе данных) или непосредственное хранение паролей вместо хэша пароля.
-
Хэш пароля это значение фиксированной длины, созданное путём обработки пароля через криптографическую хэш-функцию. Django может проверить правильность введённого пароля, пропустив его через хэш-функцию и сравнив вывод с сохранённым значением хэша. Благодаря «одностороннему» характеру функции, даже если сохранённое хэш-значение скомпрометировано, злоумышленнику будет сложно определить исходный пароль.
-
Django, по умолчанию, обеспечивает защиту от многих уязвимостей, включая SQL-инъекцию, межсайтовый скриптинг, подделку межсайтовых запросов и кликджекинг (см. Website security для получения дополнительной информации об этих атаках).
-
Масштабируемым
-
Django использует компонентную “shared-nothing” архитектуру (каждая её часть  независима от других и, следовательно, может быть заменена или изменена, если это необходимо). Чёткое разделение частей означает, что Django может масштабироваться при увеличении трафика, путём добавления оборудования на любом уровне: серверы кэширования, серверы баз данных или серверы приложений. Одни из самых загруженных сайтов успешно масштабировали Django (например, Instagram и Disqus, если назвать только два из них).
-
Удобным в сопровождении
-
Код Django написан с использованием принципов и шаблонов проектирования, которые поощряют создание поддерживаемого и повторно используемого кода. В частности, в нём используется принцип «Don't Repeat Yourself» (DRY, «не повторяйся»), поэтому нет ненужного дублирования, что сокращает объём кода. Django также способствует группированию связанных функциональных возможностей в повторно используемые «приложения» и, на более низком уровне, группирует связанный код в модули (в соответствии с шаблоном Model View Controller (MVC)).
-
Переносным
-
Django написан на Python, который работает на многих платформах. Это означает, что вы не привязаны к какой-либо конкретной серверной платформе и можете запускать приложения на многих версиях Linux, Windows и Mac OS X. Кроме того, Django хорошо поддерживается многими веб-хостингами, которые часто предоставляют определённую инфраструктуру и документацию для размещения сайтов Django.
-
- -

Как он появился?

- -

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

- -

Django продолжает расти и улучшаться с момента его первого релиза (1.0) в сентябре 2008 года до недавно выпущенной версии 3.1 (2020). В каждой версии добавлены новые функциональные возможности и исправлены ошибки, начиная от поддержки новых типов баз данных, шаблонизаторов и кэширования, до добавления «общих» функций просмотра и классов (уменьшающих объём кода, который разработчики должны писать для ряда программных задач).

- -
-

Заметка: Ознакомтесь с примечаниями к версии на сайте Django, чтобы увидеть что изменилось в последних версиях и как много работы было проделано, чтобы улучшить Django.

-
- -

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

- -

Насколько популярен Django?

- -

Нет никаких доступных и окончательных оценок популярности серверных фреймворков (хотя сайты наподобие Hot Framework и пытаются оценить популярность, используя такие механизмы, как подсчёт количества проектов на GitHub и вопросов на StackOverflow для каждой платформы). Лучший вопрос — «достаточно ли Django популярен», чтобы избежать проблем непопулярных платформ. Продолжает ли он развиваться? Можете ли вы получить помощь, если вам нужно? Найдёте ли вы оплачиваемую работу, если изучите Django?

- -

Основываясь на количестве крупных сайтов, которые используют Django, количестве участников и количестве людей, предоставляющих как бесплатную, так и платную поддержку, можно ответить: да, Django — популярный фреймворк!

- -

Django используют такие крупные сайты, как Disqus, Instagram, Knight Foundation, MacArthur Foundation, Mozilla, National Geographic, Open Knowledge Foundation, Pinterest и Open Stack (источник: обзорная страница Django).

- -

Является ли Django гибким?

- -

Веб-фрейморки часто можно поделить на "гибкие" и "негибкие".

- -

Негибкие - это те, у которых есть "правильный путь" для решения какой-либо конкретной задачи. Они часто поддерживают быстрое развёртывание в определенной области (решение проблем определенного типа), потому что правильный способ сделать что-либо обычно хорошо понимается и хорошо документируется. Однако они могут быть менее гибкими при решении проблем за пределами их основной сферы и, как правило, предлагают меньше вариантов того, какие компоненты и подходы они могут использовать.

- -

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

- -

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

- -

Как выглядит код Django?

- -

На традиционном информационом веб-сайте веб-приложение ожидает HTTP-запросы от веб-браузера (или другого клиента). Когда запрос получен, приложение разрабатывает то, что необходимо на основе URL-адреса и, возможно, данных в POST или GET запросах. В зависимости от того, что требуется, далее он может читать или записывать информацию из базы данных или выполнять другие задачи, необходимые для удовлетворения запроса. Затем приложение вернёт ответ веб-браузеру, часто динамически создавая HTML-страницу для отображения в браузере, вставляя полученные данные в HTML-шаблон.

- -

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

- -

- - - -
-

Заметка: Django реализует уровневую архитектуру "Model View Template (MVT)". Она имеет много общего с более известной архитектурой Model View Controller

-
- - - -

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

- -

Отправка запроса в правильное view (urls.py)

- -

Сопоставитель URL-адресов обычно содержится в файле urls.py. В примере ниже сопоставитель (urlpatterns) определяет список сопоставлений междумаршрутами (определёнными URL-шаблонами) и соотвествующими функциями отображения (view). Если получен HTTP-запрос, который имеет URL-адрес, соответствующий определённому шаблону, то затем будет вызвана связанная функция отображения (view) и передана в запрос.

- -
urlpatterns = [
-    path('admin/', admin.site.urls),
-    path('book/<int:id>/', views.book_detail, name='book_detail'),
-    path('catalog/', include('catalog.urls')),
-    re_path(r'^([0-9]+)/$', views.best),
-]
- -

Объект urlpatterns является списком функций path() и/или re_path() (в Python списки определяются с помощью квадратных скобок, внутри которых элементы разделены запятыми и могут содержать необязательную завершающую запятую. Например: [item1, item2, item3,]).

- -

Первый аргумент в обоих методах - маршрут (шаблон), который будет сопоставлен. В методе path() угловые скобки используются для определения частей URL-адреса, которые будут захвачены и переданы в функцию отображения (view) в качестве именованных аргументов. Функция re_path() использует гибкий подход к сопоставлению с шаблоном, известный как регулярное выражение. Мы поговорим об этом в следующей статье!

- -

Второй аргумент — это ещё одна функция, которая будет вызываться при сопоставлении шаблона. Обозначение views.book_detail указывает, что функция называется book_detail() и может быть обнаружена в модуле с именем views (т.е. внутри файла с именем views.py).

- -

Обработка запроса (views.py)

- -

Отображения (views) — это сердце веб-приложения, принимающего HTTP-запросы от веб-клиентов и возвращающего HTTP-ответы. Между этим они используют другие ресурсы фреймворка для доступа к базам данных, шаблонам визуализации и т. д.  

- -

В приведённом ниже примере показана минимальная функция представления index(), которая могла быть вызвана нашим сопоставителем URL-адресов в предыдущем разделе. Как и все функции отображения (view), она получает объект HttpRequest в качестве параметра (request) и возвращает объект HttpResponse. В этом случае мы ничего не делаем с запросом, и наш ответ просто возвращает жёстко запрограммированную строку. Мы покажем вам запрос, который делает что-то более интересное в следующем разделе.

- -
## filename: views.py (Django view functions)
-
-from django.http import HttpResponse
-
-def index(request):
-    # Получить HttpRequest — параметр запроса
-    # Выполнить операции, используя информацию из запроса.
-    # Вернуть HttpResponse
-    return HttpResponse('Hello from Django!')
-
- -
-

Заметка: Немного Python:

- - -
- - - -

Отображения (view) обычно содержатся в файле views.py.

- -

Определение данных модели (models.py)

- -

Веб-приложения Django обрабатывают и запрашивают данные через объекты Python, называемые моделями. Модели определяют структуру хранимых данных, включая типы полей и, возможно, их максимальный размер, значения по умолчанию, параметры списка выбора, текст справки для документации, текст меток для форм и т. д. Определение модели не зависит от используемой базы данных — ваши модели будут работать в любой из них. После того как вы выбрали базу данных, которую хотите использовать, вам не нужно напрямую обращатся к ней — вы просто пишете свою структуру модели и другой код, а Django выполняет всю «грязную работу» по обращению к базе данных за вас.

- -

В приведённом ниже фрагменте кода показана очень простая модель Django для объекта Team. Класс Team наследуется от класса models.Model. Он определяет имя команды и командный уровень в качестве полей символов и задаёт максимальное количество символов, которые могут быть сохранены для каждой записи. Team_level может быть одним из нескольких значений, поэтому мы определяем его как поле выбора и предоставляем сопоставление между отображаемыми вариантами и хранимыми данными вместе со значением по умолчанию.

- -
# filename: models.py
-
-from django.db import models
-
-class Team(models.Model):
-    team_name = models.CharField(max_length=40)
-
-    TEAM_LEVELS = (
-        ('U09', 'Under 09s'),
-        ('U10', 'Under 10s'),
-        ('U11', 'Under 11s'),
-        ...  #список других командных уровней
-    )
-    team_level = models.CharField(max_length=3,choices=TEAM_LEVELS,default='U11')
-
- -
-

Заметка: Немного Python:

- - -
- -

Запросы данных (views.py)

- -

Модель Django предоставляет простой API запросов для поиска в базе данных. Поиск может осуществляться по нескольким полям одновременно, используя различные критерии (такие как exact («точный»), case-insensitive («без учёта регистра»), greater than («больше чем») и т. д.), и может поддерживать сложные выражения (например, вы можете указать поиск в командах U11, у которых есть имя команды, начинающееся с «Fr» или заканчивается на «al»).

- -

Фрагмент кода показывает функцию view (обработчик ресурсов) для отображения всех команд U09. Выделенная жирным строка показывет, как мы можем использовать модель API-запросов для того, чтобы отфильтровать все записи, где поле team_level в точности содержит текст 'U09' (обратите внимание, как эти критерии передаются функции filter() в качестве аргумента с именем поля и типом соответствия, разделённым двойным подчеркиванием: team_level__exact). 

- -
## filename: views.py
-
-from django.shortcuts import render
-from .models import Team
-
-def index(request):
-    list_teams = Team.objects.filter(team_level__exact="U09")
-    context = {'youngest_teams': list_teams}
-    return render(request, '/best/index.html', context)
-
- -
-
- -

Данная функция использует функцию render() для того, чтобы создать HttpResponse, который будет отправлен назад браузеру. Эта функция является ярлыком; она создаёт HTML-файл, комбинируя указанный HTML-шаблон и некоторые данные для вставки в шаблон (предоставляется в переменной с именем «context»). В следующем разделе мы  покажем как данные вставляются в шаблон для создания HTML-кода.

- -

Вывод данных (HTML-шаблоны)

- -

Системы шаблонов позволяют указать структуру выходного документа, используя заполнители для данных, которые будут вставлены при генерировании страницы. Шаблоны часто используются для создания HTML, но также могут создавать другие типы документов. Django «из коробки» поддерживает как собственную систему шаблонов, так и другую популярную библиотеку Python под названием Jinja2 (она также может быть использована для поддержки других систем, если это необходимо).

- -

Фрагмент кода показывает, как может выглядеть HTML-шаблон, вызванный функцией  render() из предыдущего раздела. Этот шаблон был написан с предположением, что во время отрисовки он будет иметь доступ к переменной списка, названной youngest_teams (содержащейся в контекстной переменной внутри функции render() выше). Внутри скелета HTML мы имеем выражение, которое сначала проверяет, существует ли переменная youngest_teams, а затем повторяет её в цикле for. При каждом повторе шаблон отображает значение team_name каждой команды в элементе {{htmlelement("li")}}.

- -
## filename: best/templates/best/index.html
-
-<!DOCTYPE html>
-<html lang="en">
-<head>
-  <meta charset="utf-8">
-  <title>Home page</title>
-</head>
-<body>
-  {% if youngest_teams %}
-    <ul>
-      {% for team in youngest_teams %}
-        <li>\{\{ team.team_name \}\}</li>
-      {% endfor %}
-    </ul>
-  {% else %}
-    <p>No teams are available.</p>
-  {% endif %}
-</body>
-</html>
- -

Что ещё можно сделать?

- -

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

- - - -

Резюме

- -

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

- -

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

- -
{{NextMenu("Learn/Server-side/Django/development_environment", "Learn/Server-side/Django")}}
diff --git "a/files/ru/learn/server-side/django/\321\200\320\260\320\267\320\262\320\276\321\200\320\260\321\207\320\270\320\262\320\260\320\275\320\270\320\265/index.html" "b/files/ru/learn/server-side/django/\321\200\320\260\320\267\320\262\320\276\321\200\320\260\321\207\320\270\320\262\320\260\320\275\320\270\320\265/index.html" deleted file mode 100644 index 640527b63d..0000000000 --- "a/files/ru/learn/server-side/django/\321\200\320\260\320\267\320\262\320\276\321\200\320\260\321\207\320\270\320\262\320\260\320\275\320\270\320\265/index.html" +++ /dev/null @@ -1,680 +0,0 @@ ---- -title: 'Django Руководство часть 11: Разворачивание сайта на сервере' -slug: Learn/Server-side/Django/Разворачивание -tags: - - Веб-сервер - - Для начинающих - - Разворачивание на сервере - - Развёртывание Django -translation_of: Learn/Server-side/Django/Deployment ---- -
{{LearnSidebar}}
- -
{{PreviousMenuNext("Learn/Server-side/Django/Testing", "Learn/Server-side/Django/web_application_security", "Learn/Server-side/Django")}}
- -

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

- - - - - - - - - - - - -
Требования:Завершить изучение всех предыдущих частей руководства, включая Django Руководство часть 10:  Тестирование веб-приложений в Django.
Цель:Изучить, где и как вы можете развернуть приложение Django для публичного доступа.
- -

Обзор

- -

Даже когда разработка вашего сайта завершена (или "достаточно" завершена для начала публичного тестирования), то для публичного доступа вам надо его где-то разместить.

- -

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

- - - -

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

- -

Что такое окружение развертывания?

- -

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

- - - -
-

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

-
- -

Сервер может быть вашим собственным с подключением к интернету по скоростному каналу, но более общим подходом является применение "облачных решений". Что действительно имеет значение, так это то, что ваш код запускается на некотором удаленном компьютере (возможно и "виртуальном"), в хостинговом дата-центре. Удаленный сервер обычно предоставляет определенный доступ к компьютерным ресурсам (процессору, оперативной памяти, памяти на жестких носителях и так далее) и соединение с интернетом за некоторую цену.

- -

Такой тип удаленного доступа к вычислительному/сетевому железу называется Инфраструктура как Сервис (Infrastructure as a Service - IaaS). Множество IaaS поставщиков предлагают услуги по предустановке какой-либо операционной системы, на которую вы можете установить необходимые для вашего рабочего окружения компоненты. Другие поставщики предлагают вам выбрать уже готовые полноценные рабочие окружения, возможно, включающие в себя Django и настроенный веб-сервер.

- -
-

Примечание: Готовые окружения могут сделать настройку вашего веб-сайта очень простой задачей, поскольку они имеют минимальную конфигурацию, однако, либо количество доступных опций может быть недостаточным, или они будут соответствовать устаревшей операционной системе. Часто, более предпочтительно установить необходимые компоненты самостоятельно, таким образом вы получите то, что вам необходимо, а в последующем, при обновлении системы, уже будете знать что нужно делать!

-
- -

Некоторые провайдеры поддерживают Django как часть своего предложения Платформа как Сервис (Platform as a Service - PaaS). При данном виде хостинга вам не нужно беспокоиться о большей части окружения (веб-сервере, сервере приложений, балансировщике загрузки), так как сама платформа берет это на себя (включая все моменты, касающиеся роста и развития вашего приложения). В данном случае развертывание приложения является достаточно простой задачей, - вам нужно сконцентрироваться только на вашем приложении, а не на инфраструктуре.

- -

Некоторые разработчики выбирают более гибкое решение, предоставляемое IaaS, в то время как другие предпочитают иметь наименьшие накладные расходы и простое масштабирование, предоставляемое PaaS. Когда вы только начинаете, то система типа PaaS является предпочтительной и это именно то, что мы будем использовать в данном руководстве.

- -
-

Примечание: Если вы выбираете хостинг с поддержкой Python/Django, то он должен иметь инструкцию по установке веб-сайта Django, учитывающую различные конфигурации веб-сервера, сервера приложений, обратного прокси и так далее (это не имеет значение, если вы выбрали PaaS). Например, существует множество инструкций "шаг-за-шагом" для различный конфигураций в Документации DigitalOcean по Django.

-
- -

Выбор хостинг провайдера

- -

Существует более 100 хорошо известных хостинг провайдеров, которые либо активно поддерживают, или работают с Django (их список можно увидеть в Django-дружественные хостинги). Данные поставщики предоставляют различные типы окружений (IaaS, PaaS), и различные уровни доступа к вычислительным и сетевым ресурсам, за разную цену.

- -

Некоторые вещи на которые надо обратить внимание при выборе хостинга:

- - - -

Хорошей новостью является то, что для того, чтобы начать существует достаточное количество компаний, которые предоставляют пробные "бесплатные" тарифы типа "evaluation" (для пробы), "developer" (разработка), или "hobbyist" (хобби). Всегда существуют ресурсы с ограниченым окружением, при использовании которых вам надо беспокоиться лишь о том, что они могут быть доступны лишь в течении определенного периода времени. Тем не менее, они являются отличным решением для тестирования сайтов с небольшим трафиком в реальном окружении, а также могут предоставлять простой доступ к платным ресурсам, в случае необходимости. Наиболее популярными провайдерами являются Heroku, Python Anywhere, Amazon Web Services, Microsoft Azure и так далее.

- -

Многие провайдеры имеют "basic" (базовый) тариф, предоставляющий достаточный уровень вычислительной мощности с небольшим количеством ограничений. Digital Ocean и Python Anywhere являются примерами провайдеров, которые предлагают относительно недорой базовый тариф (от $5 до $10USD в месяц).

- -
-

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

-
- -

Подготовка веб-сайта к публикации

- -

Скелет сайта был создан при помощи инструментов django-admin и manage.py, которые настроены таким образом, чтобы сделать разработку проще. Многие настройки файла проекта (определенных в settings.py) должны быть изменены перед публикацией сайта, либо из-за вопросов безопастности, либо производительности.

- -
-

Примечание: Общепринятым решением является иметь отдельный файл settings.py для публикации, который импортирует важные настройки из внешних файлов, или из переменных окружения. Доступ к данному файлу должен быть ограничен, даже если остальная часть исходного кода доступна в публичном репозитории.

-
- -

Критически важные настройки файла settings.py:

- - - -

Давайте изменим приложение LocalLibrary таким образом, чтобы читать SECRET_KEY и DEBUG из переменных окружения, если те определены, иначе использовать значения по умолчанию.

- -

Откройте /locallibrary/settings.py, закомментируйте исходное значение SECRET_KEY и добавьте новые строки, как указано ниже жирным. В течении разработки, никаких переменных окружения определено не было, таким образом будут использоваться значения по умолчанию (не имеет значения какой ключ вы используете в процессе разработки, поскольку при развертывании проекта вы будете использовать другой).

- -
# SECURITY WARNING: keep the secret key used in production secret!
-# SECRET_KEY = 'cg#p$g+j9tax!#a3cup@1$8obt2_+&k3q+pmu)5%asj6yjpkag'
-import os
-SECRET_KEY = os.environ.get('DJANGO_SECRET_KEY', 'cg#p$g+j9tax!#a3cup@1$8obt2_+&k3q+pmu)5%asj6yjpkag')
-
- -

Затем закомментируйте строку с настройкой DEBUG, а затем, добавьте новую, указанную ниже.

- -
# SECURITY WARNING: don't run with debug turned on in production!
-# DEBUG = True
-DEBUG = bool( os.environ.get('DJANGO_DEBUG', True) )
-
- -

Значение DEBUG будет True по умолчанию и станет False, в том случае, если переменная окружения DJANGO_DEBUG будет проинициализирована пустой строкой, то есть, DJANGO_DEBUG=''.

- -
-

Примечание: Было бы более понятным, если бы мы могли просто установить и снять с  DJANGO_DEBUG непосредственно на True и False , напрямую, а не использовать «любую строку» или «пустую строку» (соответственно). К сожалению, значения переменных среды хранятся как строки Python и единственная строка, которая оценивается как False является пустой строкой (например, bool('')==False).

-
- -

Весь перечень настроек для разворачивания вашего сайта находится по ссылке Deployment checklist (Django docs). Кроме того, вы можете получить список настроек, выполнив в терминале команду:

- -
python3 manage.py check --deploy
-
- -

Пример: Установка LocalLibrary на Heroku

- -

Данный раздел предоставляет демонстрацию того, как установить LocalLibrary на Heroku PaaS cloud.

- -

Почему Heroku?

- -

Heroku - один из самых продолжительных и популярных облачных сервисов PaaS. Первоначально он поддерживал только приложения Ruby, но теперь его можно использовать для размещения приложений из многих сред программирования, включая Django!

- -

Мы выбираем для использования Heroku по нескольким причинам:

- - - -

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

- -

Как работает Heroku?

- -

Heroku запускает сайты Django внутри одного, или более,  изолированых друг от друга "Dynos", которые являются виртуальными Unix-контейнерами, предоставляющими необходимое окружение для вашего приложения. Данные dynos полностью изолированы и имеют эфемерную файловую систему ("короткоживущая" файловая система, которая полностью очищается и обновляется каждый раз, когда dyno перезапускается). Единственной сущностью, которую предоставляет dynos по умолчанию, является приложение по конфигурации переменных. Heroku внутри себя применяет балансировщик загрузки для распределения веб-трафика среди всех "веб"-dynos. Поскольку dynos изолированы, Heroku может масштабировать приложение горизонтально, просто добавляя больше dynos (хотя, конечно, у вас может появиться необходимость расширить базу данных для обработки дополнительных соединений).

- -

Файловая система эфемерна, поэтому вы не можете напрямую установить необходимые для вашего приложения сервисы (то есть, базы данных, очереди, системы кэширования, хранения, сервисы электронной почты и так далее). Взамен этого, Heroku предоставляет сервисы, доступные как независимые "дополнения" ("add-ons") либо от самой Heroku, или от сторонних разработчиков. В тот момент когда ваше приложение запускается в системе, dynos получает доступ к сервисам, используя информацию, содержащуюся в переменных настройки вашего приложения.

- -

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

- - - -

Разработчики Developers взаимодействуют с Heroku при помощи специального клиентского приложения/терминала, который сильно похож на bash-скрипт Unix. Оно позволяет вам загружать код, находящийся в git-репозитории, контроллировать выполняемые процессы, смотреть логи, устанавливать конфигурационные переменные и многое другое!

- -

Для того, чтобы заставить ваше приложение работать с Heroku, нам нужно разместить наше веб-приложение в git-репозитории, добавить, перечисленные ранее, файлы, подключить дополнение (add-on) базы данных и выполнить настройки для правильной работы со статическими файлами.

- -

Когда мы выполним все, что необходимо для нашего сайта мы можем создать аккаунт Heroku, получить доступ к клиенту Heroku и использовать его, для установки нашего веб-сайта.

- -
-

Примечание: Инструкции, перечисленные ниже, соответствуют процессу работы с Heroku во время написания данной статьи (английской версии - прим. перев.). Если Heroku значительно изменит этот процесс, вы можете воспользоваться соответствующим описанием: Heroku начало работы с Django.

-
- -

На этом завершается краткий обзор начала работы с Heroku (более подробное руководство Как работает Heroku).

- -

Создание репозитория приложения на Github

- -

Heroku тесно интегрирована с системой управления версиями исходного кода git, используя ее для загрузки / синхронизации любых изменений, которые вы вносите в живую систему. Он делает это, добавляя новый «удаленный» репозиторий heroku с именем heroku, указывающий на репозиторий для вашего источника в облаке Heroku. Во время разработки вы используете git для хранения изменений в вашем «master» репозитории. Когда вы хотите развернуть свой сайт, вы синхронизируете свои изменения в репозитории Heroku.

- -
-

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

-
- -

Существует множество способов работы с git, но одним из самых простых является создание учетной записи в Github, создание репозитория там, а затем синхронизация с ним локально:

- -
    -
  1. Посетите https://github.com/ и создайте аккаунт.
  2. -
  3. После входа в систему нажмите ссылку + в верхней панели инструментов и выберите Новый репозиторий.
  4. -
  5. Заполните все поля на этой форме. Хотя они не являются обязательными, они настоятельно рекомендуются. -
      -
    • Введите имя нового репозитория (например django_local_library), и комментарий к репозиторию (например "Local Library website written in Django".
    • -
    • Нажмите на кнопку Add .gitignore и в появившемся списке выберите Python.
    • -
    • Выберите подходящую вам лицензию из списка Add license. Если не знаете для чего это - оставьте как было.
    • -
    • -

      Установите галочку напротив Initialize this repository with a README.

      -
    • -
    -
  6. -
  7. Нажмите кнопку Create repository, тем самым создав ваш репозиторий.
  8. -
  9. Перейдите на страницу вашего репозитория. Там нажмите на зелёную кнопку "Clone or download". Скопируйте URL  из текстового поляиз появившегося диалогового окна (Это будет похоже на: https://github.com/<your_git_user_id>/django_local_library.git). Здесь <your_git_user_id> - это будет ваш id пользователя git.
  10. -
- -

Когда ваш репозиторий будет создан - загрузите его себе на компьтер, следуя инструкции, описанной ниже:

- -
    -
  1. Установите git себе на компьютер (Вы можете найти версию для своей платформы здесь).
  2. -
  3. Откройте командную строку (или терминал) и выполните в нём следующую команду, используя ссылку, которую вы получили с github: -
    git clone https://github.com/<your_git_user_id>/django_local_library.git
    -
    - Это создаст подпапку (с содержанием вашего репозитория и именем вашего репозитория) внутри папки, в котрой выполнялась команда.
  4. -
  5. Перейдите в эту папку: -
    cd django_local_library.git
    -
  6. -
- -

Последний шаг. Нужно скопировать ваше Django-приложение и добавить его файлы в новый репозиторий, используя git:

- -
    -
  1. Скопируйте ваше приложение в папку репозитория (все файлы с таким же уровнем, как у manage.py, БЕЗ папки проекта, в которой эти файлы находятся).
  2. -
  3. Откройте файл с расширением .gitignore в текстовом редакторе, вставьте в самый его конец строки, приведённые ниже, а затем сохраните (этот файл "говорит" о файлах, которые не должны быть  загружены в git по умолчанию). -
    # Text backup files
    -*.bak
    -
    -#Database
    -*.sqlite3
    -
  4. -
  5. -

    Откройте командную строку или терминал и используйте add команду с флагом -A. Эта комманда сохранит изменения в репозиторий:

    - -
    git add -A
    -
  6. -
  7. Используйте команду status,  что бы убедиться, что все файлы, которые вы собираетесь добавить верны (вы хотите включить исходные файлы, а не бинарные файлы, временные файлы и т. д.). В консоль выведется что то вроде этого: -
    > git status
    -On branch master
    -Your branch is up-to-date with 'origin/master'.
    -Changes to be committed:
    -  (use "git reset HEAD <file>..." to unstage)
    -
    -        modified:   .gitignore
    -        new file:   catalog/__init__.py
    -        ...
    -        new file:   catalog/migrations/0001_initial.py
    -        ...
    -        new file:   templates/registration/password_reset_form.html
    -
  8. -
  9. Теперь, зафиксируйте файлы в локальном репозитории: -
    git commit -m "First version of application moved into github"
    -
  10. -
  11. Синхронизируете свой локальный репозиторий с сайтом Github: -
    git push origin master
    -
  12. -
- -

Когда эти операции завершатся, вернитесь на страницу Github где вы создали свой репозиторий, обновите страницу, и убедитесь, что ваше приложение полностью загружено. При надобности обновить файлы на репозитории - повторите цикл ввода команд add/commit/push.

- -
-

Подсказка: Это хороший момент для создания резервной копии вашего «ванильного» проекта — в то время как некоторые изменения, которые мы собираемся сделать в следующих разделах, могут быть полезны для развертывания на любой платформе (или разработке), которые другие могут не использовать.

- -

Лучший способ сделать это - использовать git для управления вашими изменениями. С git вы можете не только вернуться к определенной старой версии, но и сохранить ее в отдельной «ветке» ваших производственных изменений, and cherry-pick - выбрать любые изменения для перемещения между ветвями производства и развития. Изучение Git будет стоить усилий, но это выходит за рамки данной темы. Самый простой способ сделать это - просто скопировать файлы в другое место. Используйте тот подход, который наилучшим образом соответствует вашим знаниям git!

-
- -

Обновить приложение для Heroku 

- -

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

- -

Procfile

- -

 Создайте файл с именем Procfile (без расширения) в корне нашего GitHub репозитории объявить типы процессов и точки входа приложения. Скопируйте в него следующий текст:

- -
web: gunicorn locallibrary.wsgi --log-file -
- -

«web:» сообщает Heroku, что это веб динамический и может быть отправлен HTTP-трафик. Процесс, который начнется в этом динамически, - это gunicorn, который является популярным сервером веб-приложений, который рекомендует Heroku. Мы запускаем Gunicorn, используя конфигурационную информацию в модуле locallibrary.wsgi (созданный с помощью нашего скелета приложения: /locallibrary/wsgi.py).

- -

Gunicorn

- -

Gunicorn рекомендуемый http сервер с Django на Heroku (Как указанов Procfile выше). Это чистый python http сервер для WSGI приложений  которые могут запускать множество параллельных python процессов в пределах одного динамического (посмотрите Deploying Python applications with Gunicorn для получения большей информации).

- -

Также нам не понадобится Gunicorn для обслушивания нашей LocalLibrary приложения в течение разработки, мы установим это так, чтобы он стал частью наших требований к Heroku для настройки на удаленном сервере.

- -

Установка Gunicorn локально в командной строке используя пакетный менеджер pip (которые мы установили когда настраивали среду разработки):

- -
pip3 install gunicorn
-
- -

Настройка Базы Данных

- -

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

- -

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

- -

Информация о подключении базы данных предоставляется на web dyno, используя конфигурационную переменную с именем DATABASE_URL. Вместо того, чтобы жестко кодировать эту информацию в Django, Heroku рекомендует разработчикам использовать dj-database-url пакет для анализа DATABASE_URL переменную окружения и автоматически преобразовать ее в желаемый формат конфигурации Django. В дополнение к установке пакета dj-database-url нам также потребуется установить psycopg2, поскольку Django нуждается в этом, чтобы взаимодействовать с базами данных Postgres.

- -
dj-database-url (Django конфигурации базы данных из переменной окружения)
- -

Установите dj-database-url локально, чтобы он стал частью наших требований к настройке Heroku на удаленном сервере:

- -
$ pip3 install dj-database-url
-
- -
settings.py
- -

Откройте /locallibrary/settings.py и скопируйте следующую конфигурацию в нижнюю часть файла:

- -
# Heroku: Update database configuration from $DATABASE_URL.
-import dj_database_url
-db_from_env = dj_database_url.config(conn_max_age=500)
-DATABASES['default'].update(db_from_env)
- -
-

Заметка:

- - -
- -
psycopg2 (Python Postgres database support)
- -

Django нуждается в psycopg2 для работы с базами данных Postgres, и вам нужно будет добавить это в файл требований.txt для Heroku, чтобы установить это на удаленном сервере (как описано в разделе требований ниже).

- -

Django будет использовать нашу базу данных SQLite локально по умолчанию, поскольку переменная среды DATABASE_URL не задана в нашей локальной среде. Если вы хотите полностью перейти на Postgres и использовать нашу бесплатную базу данных Heroku для разработки и производства, то вы можете. Например, чтобы установить psycopg2 и его зависимости локально в системе на базе Linux, вы должны использовать следующие команды bash / terminal:

- -
sudo apt-get install python-pip python-dev libpq-dev postgresql postgresql-contrib
-pip3 install psycopg2
-
- -

Инструкции по установке для других платформ можно найти на веб-сайте psycopg2.

- -

Однако вам не нужно это делать - вам не нужно, чтобы PostGreSQL был активным на локальном компьютере, если вы передаете его в Heroku в качестве требования в файле требований.txt (см. Ниже).

- -

Обслуживание статических файлов в производстве

- -


- Во время разработки мы использовали Django и веб-сервер разработки Django для обслуживания наших статических файлов (CSS, JavaScript и т. Д.). В производственной среде вместо этого мы обычно обслуживаем статические файлы из сети доставки контента (CDN) или веб-сервера.

- -
-

Примечание. Обслуживание статических файлов через Django / веб-приложение неэффективно, потому что запросы должны проходить через ненужный дополнительный код (Django), а не обрабатываться непосредственно веб-сервером или полностью отдельным CDN. Хотя это не имеет значения для местного использования во время разработки, это будет иметь значительное влияние на производительность, если мы будем использовать тот же подход в производстве.

-
- -

Чтобы упростить размещение статических файлов отдельно от веб-приложения Django, Django предоставляет средство сбора данных для сбора этих файлов для развертывания (имеется переменная параметров, определяющая, где файлы должны собираться при запуске collectstatic). Шаблоны Django относятся к месту размещения статических файлов относительно переменной параметров (STATIC_URL), так что это можно изменить, если статические файлы перемещаются на другой хост / сервер.

- -

Соответствующими параметрами настройки являются:

- -

     STATIC_URL: это базовое расположение URL, из которого будут загружены статические файлы, например, на CDN. Это используется для переменной статического шаблона, доступ к которой осуществляется в нашем базовом шаблоне (см. Учебник по Django Part 5: Создание нашей домашней страницы).
-       STATIC_ROOT: Это абсолютный путь к каталогу, в котором инструмент «collectstatic» Django будет собирать любые статические файлы, упомянутые в наших шаблонах. После их сбора они затем могут быть загружены в группу, где бы файлы не размещались.
-       STATICFILES_DIRS: В этом списке перечислены дополнительные каталоги, в которых инструмент коллективного поиска Django должен искать статические файлы.

- -
settings.py
- -

Откройте /locallibrary/settings.py и скопируйте следующую конфигурацию в нижнюю часть файла. BASE_DIR уже должен быть определен в вашем файле (STATIC_URL, возможно, уже был определен в файле, когда он был создан. В то время как это не причинит вреда, вы также можете удалить дублируемую предыдущую ссылку).

- -
# Static files (CSS, JavaScript, Images)
-# https://docs.djangoproject.com/en/1.10/howto/static-files/
-
-# The absolute path to the directory where collectstatic will collect static files for deployment.
-STATIC_ROOT = os.path.join(BASE_DIR, 'staticfiles')
-
-# The URL to use when referring to static files (where they will be served from)
-STATIC_URL = '/static/'
-
- -

Фактически мы будем делать файл, используя библиотеку WhiteNoise, которую мы устанавливаем и настраиваем в следующем разделе.

- -

Для получения дополнительной информации см. Django и Static Assets (документы Heroku).

- -

WhiteNoise
- Существует множество способов обслуживания статических файлов на производстве (мы видели соответствующие настройки Django в предыдущих разделах). Heroku рекомендует использовать проект WhiteNoise для обслуживания статических активов непосредственно из Gunicorn в производстве.

- -
-

Заметка: Heroku автоматически вызывает collectstatic и готовит ваши статические файлы для использования WhiteNoise после того, как он загрузит ваше приложение. Посмотрите WhiteNoise документацию для объяснения того, как она работает, и почему реализация является относительно эффективным методом для обслуживания этих файлов.

-
- -

Шаги по настройке WhiteNoise для использования в проекте:

- -
WhiteNoise
- -

Установите WhiteNoise локально, используя следующую команду:

- -
$ pip3 install whitenoise
-
- -
settings.py
- -

Чтобы установить WhiteNoise в приложение Django, откройте /locallibrary/settings.py, найдите параметр MIDDLEWARE и добавьте WhiteNoiseMiddleware в верхней части списка, чуть ниже SecurityMiddleware:

- -
MIDDLEWARE = [
-    'django.middleware.security.SecurityMiddleware',
-    'whitenoise.middleware.WhiteNoiseMiddleware',
-    'django.contrib.sessions.middleware.SessionMiddleware',
-    'django.middleware.common.CommonMiddleware',
-    'django.middleware.csrf.CsrfViewMiddleware',
-    'django.contrib.auth.middleware.AuthenticationMiddleware',
-    'django.contrib.messages.middleware.MessageMiddleware',
-    'django.middleware.clickjacking.XFrameOptionsMiddleware',
-]
-
- -

При желании вы можете уменьшить размер статических файлов при их обслуживании (это более эффективно). Просто добавьте следующее в конец /locallibrary/settings.py:

- -
# Simplified static file serving.
-# https://warehouse.python.org/project/whitenoise/
-STATICFILES_STORAGE = 'whitenoise.storage.CompressedManifestStaticFilesStorage'
-
- -

Requirements

- -

Требования Python вашего веб-приложения должны храниться в файле requirements.txt в корневом каталоге вашего репозитория. После этого Heroku автоматически установит их при восстановлении вашей среды. Вы можете создать этот файл с помощью pip в командной строке (запустите в корне repo):

- -
pip3 freeze > requirements.txt
- -

После установки всех разных зависимостей выше, файл requirements.txt должен иметь по меньшей мере эти перечисленные элементы (хотя номера версий могут отличаться). Удалите любые другие зависимости, не перечисленные ниже, если вы явно не добавили их для этого приложения.

- -
dj-database-url==0.4.1
-Django==1.10.2
-gunicorn==19.6.0
-psycopg2==2.6.2
-whitenoise==3.2.2
-
- -
-

Убедитесь, что строка  psycopg2, подобная приведенной выше, присутствует! Даже если вы не установили это локально, вы должны добавить это в requirements.txt.

-
- -

Среда выполнения

- -

Файл runtime.txt, если определён, говорит Heroku, какой язык программирования использовать. Создайте файл в корне репо и добавьте следующий текст:

- -
python-3.5.2
- -
-

Заметка: Heroku поддерживает только небольшое количество Python runtimes. (на момент написания статьи, в том числе и выше). Heroku будет использовать поддерживаемую среду выполнения независимо от значения, указанного в этом файле.

-
- -

Сохраните изменения в Github и перепроверьте

- -

Далее мы сохраним все наши изменения в Github. В терминале (whist внутри нашего репозитория) введите следующие команды:

- -
git add -A
-git commit -m "Added files and changes required for deployment to heroku"
-git push origin master
- -

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

- -
python3 manage.py runserver
- -

Теперь мы должны быть готовы начать развертывание LocalLibrary на Heroku.

- -

Получить аккаунт в heroku

- -

Чтобы начать использовать Heroku, вам сначала нужно создать учетную запись:

- - - -

Установка клиента

- -

Загрузите и установите клиент Heroku, следуя инструкциям Heroku здесь.

- -

После установки клиента вам будут дотупны команды. Например, чтобы получить справку о клиенте:

- -
heroku help
-
- -

Создание и загрузка веб-сайта

- -

Чтобы создать приложение, мы запускаем команду «create» в корневом каталоге нашего репозитория. Это создает git remote («указатель на удаленный репозиторий»), названный heroku в нашей локальной среде git.

- -
heroku create
- -
-

Заметка: Вы можете назвать удаленный, если хотите, указав значение после «create». Если вы этого не сделаете, вы получите случайное имя. Имя используется в URL-адресе по умолчанию.

-
- -

Затем мы можем подтолкнуть наше приложение в репозиторий heroku как показано ниже. Это позволит загрузить приложение, упаковать его в dyno, запустить collectstatic, и запустить сам сайт.

- -
git push heroku master
- -

Если нам повезет, приложение «заработает» на сайте, но оно не будет работать должным образом, потому что мы не настроили таблицы базы данных для использования нашим приложением. Для этого нам нужно использовать команду  heroku run и запустить "one off dyno" для выполнения операции переноса. Введите в терминал следующую команду:

- -
heroku run python manage.py migrate
- -

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

- -
heroku run python manage.py createsuperuser
- -

Как только это будет завершено, мы можем посмотреть сайт. Он должен работать, хотя в нем еще нет книг. Чтобы открыть браузер на новом веб-сайте, используйте команду:

- -
heroku open
- -

Создайте несколько книг на сайте администратора и проверьте, работает ли сайт, как вы ожидаете.

- -

Управление аддонами

- -

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

- -
>heroku addons
-
-Add-on                                     Plan       Price  State
-─────────────────────────────────────────  ─────────  ─────  ───────
-heroku-postgresql (postgresql-flat-26536)  hobby-dev  free   created
- └─ as DATABASE
- -

Здесь мы видим, что у нас есть только одна надстройка, база данных postgres SQL. Это бесплатно и автоматически создается при создании приложения. Вы можете открыть веб-страницу, чтобы более подробно изучить надстройку базы данных (или любое другое дополнение), используя следующую команду:

- -
heroku addons:open heroku-postgresql
-
- -

Другие команды позволяют создавать, уничтожать, обновлять и понижать аддоны (используя аналогичный синтаксис для открытия). Для получения дополнительной информации см.  Managing Add-ons (Heroku docs).

- -

Настройка переменных конфигурации

- -

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

- -
>heroku config
-
-=== locallibrary Config Vars
-DATABASE_URL: postgres://uzfnbcyxidzgrl:j2jkUFDF6OGGqxkgg7Hk3ilbZI@ec2-54-243-201-144.compute-1.amazonaws.com:5432/dbftm4qgh3kda3
- -

Если вы вспомните из раздела, посвященного  getting the website ready to publish, мы должны установить переменные среды для DJANGO_SECRET_KEY и DJANGO_DEBUG. Давайте сделаем это сейчас.

- -
-

Заметка: Секретный ключ должен быть действительно секретным! Один из способов генерации нового ключа - создать новый проект Django (django-admin startproject someprojectname) а затем получить ключ, который генерируется для вас в его settings.py.

-
- -

Мы устанавливаем  DJANGO_SECRET_KEY используя команду config:set (как показано ниже). Не забудьте использовать свой секретный ключ!

- -
>heroku config:set DJANGO_SECRET_KEY=eu09(ilk6@4sfdofb=b_2ht@vad*$ehh9-)3u_83+y%(+phh&=
-
-Setting DJANGO_SECRET_KEY and restarting locallibrary... done, v7
-DJANGO_SECRET_KEY: eu09(ilk6@4sfdofb=b_2ht@vad*$ehh9-)3u_83+y%(+phh
-
- -

Аналогично мы устанавливаем  DJANGO_DEBUG:

- -
>heroku config:set DJANGO_DEBUG=''
-
-Setting DJANGO_DEBUG and restarting locallibrary... done, v8
- -

Если вы посетите веб-сайт сейчас, вы получите ошибку "Bad request" , потому что в  ALLOWED_HOSTS надо внести параметры, если у вас DEBUG=False (в качестве меры безопасности). Откройте /locallibrary/settings.py и измените ALLOWED_HOSTS для включения вашего базового URL-адреса приложения (например, 'locallibrary1234.herokuapp.com') URL, который вы обычно используете на локальном сервере разработки.

- -
ALLOWED_HOSTS = ['<your app URL without the https:// prefix>.herokuapp.com','127.0.0.1']
-# For example:
-# ALLOWED_HOSTS = ['fathomless-scrubland-30645.herokuapp.com','127.0.0.1']
-
- -

Затем сохраните настройки и передайте их в репозиторий Github и в Heroku:

- -
git add -A
-git commit -m 'Update ALLOWED_HOSTS with site and development server URL'
-git push origin master
-git push heroku master
- -
-

После завершения обновления сайта на Heroku введите URL-адрес, который не существует (например,  /catalog/doesnotexist/). Раньше это отображало бы подробную страницу отладки, но теперь вы должны просто увидеть простую страницу «Не найдено».

-
- -

Отладка

- -

Клиент Heroku предоставляет несколько инструментов для отладки:

- -
heroku logs  # Show current logs
-heroku logs --tail # Show current logs and keep updating with any new results
-heroku config:set DEBUG_COLLECTSTATIC=1 # Add additional logging for collectstatic (this tool is run automatically during a build)
-heroku ps   #Display dyno status
-
- -

Если вам нужно больше информации, предоставленной здесь, вам нужно будет начать изучать Django Logging.

- - - -

Итоги

- -

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

- -

Смотрите также

- - - -

{{PreviousMenuNext("Learn/Server-side/Django/Testing", "Learn/Server-side/Django/web_application_security", "Learn/Server-side/Django")}}

- -

В этом модуле

- - diff --git "a/files/ru/learn/server-side/django/\321\201\320\265\321\201\321\201\320\270\320\270/index.html" "b/files/ru/learn/server-side/django/\321\201\320\265\321\201\321\201\320\270\320\270/index.html" deleted file mode 100644 index 5f7d492c72..0000000000 --- "a/files/ru/learn/server-side/django/\321\201\320\265\321\201\321\201\320\270\320\270/index.html" +++ /dev/null @@ -1,181 +0,0 @@ ---- -title: 'Руководство часть 7: Сессии' -slug: Learn/Server-side/Django/Сессии -tags: - - django - - Джанго - - Для начинающих - - Изучение - - Питон - - Руководство - - Серверная сторона - - Статья - - применение сессий - - сессии -translation_of: Learn/Server-side/Django/Sessions ---- -
{{LearnSidebar}}
- -
{{PreviousMenuNext("Learn/Server-side/Django/Generic_views", "Learn/Server-side/Django/authentication_and_sessions", "Learn/Server-side/Django")}}
- -

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

- - - - - - - - - - - - -
Требования:Завершить изучение всех предыдущих разделов, включая Django Руководство Часть 6: Обобщенные отображения списков и детальной информации
Цель:Понимать как применять сессии.
- -

Обзор

- -

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

- -

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

- -

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

- -

Что такое сессии?

- -

Все взаимодействия между браузерами и серверами осуществляются при помощи протокола HTTP, который не сохраняет свое состояние (stateless). Данный факт означает, что сообщения между клиентом и сервером являются полностью независимыми один от другого — то есть не существует какого-либо представления "последовательности", или поведения в зависимости от предыдущих сообщений. В результате, если вы хотите создать сайт который будет отслеживать взаимодействие с клиентом (браузером), вам нужно реализовать это самостоятельно.

- -

Сессии являются механизмом, который использует Django (да и весь остальной "Интернет") для отслеживания "состояния" между сайтом и каким-либо браузером. Сессии позволяют вам хранить произвольные данные браузера и получать их в тот момент, когда между данным браузером и сайтом устанавливается соединение. Данные получаются и сохраняются в сессии при помощи соответствующего "ключа".

- -

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

- -

Подключение сессий

- -

Сессии стали доступны автоматически в тот момент, когда мы создали скелет сайта (во второй части руководства).

- -

Необходимые конфигурации выполняются в разделах INSTALLED_APPS и MIDDLEWARE файла проекта (locallibrary/locallibrary/settings.py), как показано ниже:

- -
INSTALLED_APPS = [
-    ...
-    'django.contrib.sessions',
-    ....
-
-MIDDLEWARE = [
-    ...
-    'django.contrib.sessions.middleware.SessionMiddleware',
-    ....
- -

Применение сессий

- -

Вы можете получить доступ к переменной session, в соответствующем отображении, через параметр request (HttpRequest передается как первый аргумент в каждое отображение). Переменная сессии является связью с определенным пользователем (или, если быть более точным, связью с определенным браузером, который определяется при помощи идентификатора (id) сессии, получаемого из куки браузера).

- -

Переменная (или поле) session является объектом-словарем, который служит для чтения и записи неограниченное число раз. С ним вы можете выполнять любые стандартные операции, включая очистку всех данных, проверку наличия ключа, циклы по данным и так далее. Большую часть времени вы будете тратить на  обычные "словарные" операции - получения и установки значений.

- -

Ниже представлены фрагменты кода, которые показывают вам как получать, задавать и удалять некоторые данные при помощи ключа "my_car", связанного с текущей сессией (браузером). 

- -
-

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

-
- -
# Получение значения сессии при помощи ключа(то есть, 'my_car').
-# Если такого ключа нет, то возникнет ошибка KeyError
-my_car = request.session['my_car']
-
-# Получение значения сессии. Если значения не существует,
-# то вернется значение по умолчанию ('mini')
-my_car = request.session.get('my_car', 'mini')
-
-# Передача значения в сессию
-request.session['my_car'] = 'mini'
-
-# Удаление значения из сессии
-del request.session['my_car']
-
- -

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

- -

Хранение данных сессии

- -

По умолчанию Django сохраняет данные сессии в базу данных и отправляет соответствующие куки клиенту только тогда, когда сессия была изменена, или удалена. Если вы обновляете какие-либо данные при помощи ключа сессии, как показано в предыдущем фрагменте, тогда вам не надо беспокоиться о процессе сохранения! Например:

- -
# Данное присваивание распознается как обновление сессии
-# и данные будут сохранены
-request.session['my_car'] = 'mini'
- -

Если вы обновлете информацию внутри данных сессии, тогда Django не распознает эти изменения и не выполнит сохранение данных (например, если вы изменили "wheels" внутри переменной "my_car", как показано ниже). В таких случаях вам надо явно указывать, что сессия была изменена.

- -
# Объект сессии модифицируется неявно.
-# Изменения НЕ БУДУТ сохранены!
-request.session['my_car']['wheels'] = 'alloy'
-
-# Явное указание, что данные изменены.
-# Сессия будет сохранена, куки обновлены (если необходимо).
-request.session.modified = True
-
- -
-

Примечание: Вы можете изменить поведение сессий таким образом, чтобы они записывали любое свое изменение в базу данных и отправляли куки, при каждом запросе, путем установки SESSION_SAVE_EVERY_REQUEST = True, в файле настроек проекта (locallibrary/locallibrary/settings.py).

-
- -

Простой пример — получение числа визитов

- -

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

- -

Откройте /locallibrary/catalog/views.py и добавьте изменения, выделенных жирным, ниже. 

- -
def index(request):
-    ...
-
-    num_authors=Author.objects.count()  # The 'all()' is implied by default.
-
-    # Number of visits to this view, as counted in the session variable.
-    num_visits=request.session.get('num_visits', 0)
-    request.session['num_visits'] = num_visits+1
-
-    # Render the HTML template index.html with the data in the context variable.
-    return render(
-        request,
-        'index.html',
-        context={'num_books':num_books,'num_instances':num_instances,'num_instances_available':num_instances_available,'num_authors':num_authors,
-            'num_visits':num_visits}, # num_visits appended
-    )
- -

В первую очередь мы получаем значение 'num_visits' из сессии, возвращая 0, если оно не было установлено ранее. Каждый раз при получении запроса, мы увеличиваем данное значение на единицу и сохраняем его обратно в сессии (до следующего посещения данной страницы пользователем). Затем переменная num_visits передается в шаблон через переменную контекста context.  

- -
-

Примечание: Можно проверить наличие поддержки куки в браузере (для примера, смотрите Как использовать сессии), или разработать наш UI таким образом, чтобы это не имело значения.

-
- -

Для показа значения переменной, из следующего фрагмента добавьте нижнюю строчку кода в ваш шаблон главной страницы сайта (/locallibrary/catalog/templates/index.html), в его нижний раздел "Dynamic content":

- -
<h2>Dynamic content</h2>
-
-<p>The library has the following record counts:</p>
-<ul>
-<li><strong>Books:</strong> \{{ num_books }}</li>
-<li><strong>Copies:</strong> \{{ num_instances }}</li>
-<li><strong>Copies available:</strong> \{{ num_instances_available }}</li>
-<li><strong>Authors:</strong> \{{ num_authors }}</li>
-</ul>
-
-<p>You have visited this page \{{ num_visits }}{% if num_visits == 1 %} time{% else %} times{% endif %}.</p>
-
- -

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

- - - -

Итоги

- -

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

- -

В наших следующих статьях мы рассмотрим фреймворк аутентификации и авторизации (разрешение доступа, permission), и покажем вам как поддерживать пользовательские аккаунты.

- -

Смотрите также

- - - -

{{PreviousMenuNext("Learn/Server-side/Django/Generic_views", "Learn/Server-side/Django/Authentication", "Learn/Server-side/Django")}}

-- cgit v1.2.3-54-g00ecf