В этой части будем реализовывать механизм авторизации пользователей через страницы логина и регистрации на Django 1.11 c валидацией форм и возможностью logout. В статье приведен код для python3.
Создание проекта
Для начала создадим проект myproject через консоль в нужной нам папке и перейдем в папку проекта. Внутри проекта создадим приложение джанго - registration
1
2
3
$ django-admin startproject myproject
$ cd myproject
$ python manage.py startapp registration
теперь структура внутри registration выглядит следующим образом
1
2
3
4
5
6
7
8
│ admin.py
│ apps.py
│ models.py
│ tests.py
│ views.py
│ __init__.py
│
└───migrations
Так как в Django реализована архитектура MVC, то в нашем случае “M” - models.py, это файл, где прописывается логика взаимодействия с базой данных, “C”, в случае Django “Template”, это представление данных в браузере через html, а views это бизнес-логика, как применять модели и шаблоны. Годная картинка по теме:
Так как авторизация в нашем случае для тестового проекта, а не для большого e-commerce сайта, то реализуем взаимодействие с базой данных не через models.py, а через форму и встроенную в Django модель User, так что файл models.py можем удалять, как и tests.py - в этой части мы их оставим. Теперь структура нашего приложения выглядит так:
1
2
3
4
5
6
7
│ admin.py
│ apps.py
│ forms.py
│ views.py
│ __init__.py
│
└───migrations
Всего у нас будет три страницы html: для тех, кто пришел в первый раз(login.html), для регистрации(register.html) и для тех, кто успешно прошел регистрацию и зашел через логин(success.html).
Итого у нас два use-case
для пришедших в первый раз: login -> register -> login -> success
для пришедших повторно login -> success
Обрабатывать результаты будем через формы и регистрационные данные записывать в базу данных sqlite3(которая создается по умолчанию для проекта Django). Перейдем к коду.
Находим наши страницы
Для примера возьмем бутстраповские страницы логина и регистрации и немного их изменим, дополнив тегами Jinja2.
Все темплейты хранятся в папке templates, которую мы создадим в основном проекте.Таким образом, структура проекта со всеми добавленными темплейтами будет выглядеть так:
1
2
3
4
5
6
7
8
9
10
11
|-- myproject
| `-- __pycache__
|-- registration
| |-- __pycache__
| `-- migrations
| `-- __pycache__
|-- templates
| -- base.html
| -- login.html
| -- register.html
` -- success.html
Код страницы логина. При сабмите формы идет ссылка на функцию account_login c post запросом. {% csrf_token %} это обеспечение безопасности от межсайтовой подделки запроса. Используется в формах в связи с post-запросами. Они опаснее обычных get запросов, т.к. взаимодействуют с базой данных.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
{% extends "base.html" %}
{% block title %}Login{% endblock %}
{% block content %}
<divclass="container"style="margin-top:40px">
<divclass="row">
<divclass="col-sm-6 col-md-4 col-md-offset-4">
<divclass="panel panel-default">
<divclass="panel-heading">
<strong> Sign in to continue</strong>
</div>
<divclass="panel-body">
{% if error %}
<pclass="text-danger">Please enter a correct username and password.
И страницу успешного входа мы увидим уже в конце, если у нас все получится=)
В начале каждого документа стоит тег {% extends "base.html" %}, что является расширением одного темплейта на базе основного, в Джанго основной темплейт классически называется base.html. Это удобно, так как не приходится копировать один и тот же код в хедере разных страниц. Получается, что весь контент отдельной страницы помещается между тегами {% block content %} и {% endblock %} . Подробнее можно почитать здесь.
Для обработки страниц в файле views.py пишем три функции на каждую из страниц (login,register,success) и одну функцию logout. Импортируем нужные нам модули Django, из интересных штук тут есть декоратор login_required, который “дополняет” функцию успешного входа - success(), проверяя прошел ли предварительно логин в системе.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
from django.contrib.auth.decorators import login_required
from django.contrib.auth.forms import AuthenticationForm
from django.contrib.auth.models import User
from django.contrib.auth import login, logout
from django.template.response import TemplateResponse
from django.http import HttpResponseRedirect
from django.urls import reverse
from .forms import UserCreateForm
deflogin(request):
""" Функция, которая принимает http-запрос, если произведен get-запрос,
возвращает страницу логина. Если post-запрос, берет данные из базы данных,
и проверяет логин и пароль с помощью встроенной формы AuthenticationForm,
при успешном сценарии вызывает метод login, который принимает объект
реквеста и юзера, сохраняет id usera в сессию Django
В функции register мы ссылаемся на форму UserCreateForm, которая находится в forms.py. В этом файле мы прописываем нужные нам поля из страницы регистрации. Метод clean() выполняет роль проверки совпадения значений, которые пользователь указывает в “введите пароль” и “повторно введите пароль”.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
from django.forms import Form, CharField, EmailField
if cleaned_data.get('password') != cleaned_data.get('confirm_password'):
self._errors['password'] = ErrorList('The passwords you entered do not match')
return cleaned_data
Конфигурация URL-ов
Теперь самое время настроить ссылки, по которым мы будем обращаться к нашим функциям во views. Для этого в файле urls.py внутри папки приложения registration пропишем следующее:
Таким образом, мы обозначаем, что если пользователь перешел по ссылке адресприложения/account/login, то вызывается функция views.login, если другой запрос - остальные ссылки по аналогии. Для конфигурации ссылок в Джанго используются регулярные выражения, тема обширная, думаю, для отдельной статьи. Пока что просто воспримем как есть.
Затем включим эти url в наше основное приложение - myproject, чтобы обращаться к приложению registration. Для этого в папке myproject в файле urls.py исправим следующее
1
2
3
4
5
6
7
8
from django.conf.urls import url, include # добавляем метод include
from django.contrib import admin # это прописывается автоматически, не меняем
urlpatterns = [
url(r'^admin/', admin.site.urls), # также не меняем
url(r'^account/', include('registration.urls')) # добавляем urls нашего приложения registration
]
Теперь мы должны получить страницу логина при входе. Таким образом, ссылки как бы нанизываются друг на друга. account + login в url передаст в браузер нужную нам страницу логина. Попробуем. Для корректной работы формы сделаем миграцию базы данных и запустим проект.
1
2
3
$ python manage.py makemigrations
$ python manage.py migrate
$ python manage.py runserver
Результаты
Ну чтож, даже ребята со стоковых фото считают, что мы молодцы. Уж они явно что-то знают.
Код этой статьи можно найти в моем репозитории на github.