В Django присутствуют низкоуровневые средства для аутентификации и авторизации пользователей.
Все что нам необходимо — это внедрить данный функционал: создав форму для входа и несколько представлений.
Форма
Приступаем к созданию формы, открываем в каталоге приложения accounts файл forms.py и добавляем следующие строки:
from django.contrib.auth import authenticate, login
class AuthForm(forms.Form):
email = forms.EmailField(label='Адрес электронной почты', max_length=254,
widget=forms.EmailInput(attrs={'autofocus': ''}))
password = forms.CharField(label='Пароль', max_length=255, strip=False, widget=forms.PasswordInput)
def __init__(self, *args, **kwargs):
super(AuthForm, self).__init__(*args, **kwargs)
self.user = None
def clean(self):
email = self.cleaned_data.get('email')
password = self.cleaned_data.get('password')
if email and password:
self.user = authenticate(email=email, password=password)
if not self.user:
raise forms.ValidationError('Введены неправильные учетные данные или пользователь неактивен')
return self.cleaned_data
def login(self, request):
login(request, self.user)
Представления
Далее открываем файл views.py и добавляем следующее:
from django.contrib.auth import logout
@anonymous_required
def login_view(request):
form = forms.AuthForm(request.POST or None)
if form.is_valid():
form.login(request)
return redirect('index')
return render(request, 'accounts/login.html', {
'form': form,
})
def logout_view(request):
logout(request)
return redirect('accounts:login')
В login_view мы отображаем форму аутентификации и в случае правильного заполнения проводим авторизацию пользователя и затем перенаправляем на главную станицу. В случае если аутентификация прошла по каким-либо причинам не успешно — отображаем шаблон с подсказками как исправить ситуацию.
В свою очередь logout_view не использует каких-либо дополнительных проверок или действий и просто запускает штатную процедура выхода и затем перенаправляет на страницу входа.
Маршруты
Открываем urls.py и приводим файл к следующему виду:
from django.conf.urls import url
from . import views
app_name = 'accounts'
urlpatterns = [
url(r'^join/$', views.join_view, name='join'),
url(r'^join/confirm/(?:(?P<code>\w+)/)?$', views.join_confirm_view, name='join_confirm'),
url(r'^join/resend/$', views.join_resend_view, name='join_resend'),
url(r'^login/$', views.login_view, name='login'),
url(r'^logout/$', views.logout_view, name='logout'),
]
Шаблоны
Переходим к заключительному шагу — создание шаблонов.
В директории templates выбираем подкаталог accounts и создаем файл login.html:
{% extends 'base.html' %}
{% block title %}Войти{% endblock %}
{% block main %}
<div class="accounts-login">
<h1>Войти</h1>
<form action="{% url 'accounts:login' %}" method="post">
{% csrf_token %}
{% include 'core/form_fields.html' %}
<button type="submit" class="btn btn-success">Войти</button>
</form>
<div class="links">
<p><a href="{% url 'accounts:join' %}">Присоединиться к нам!</a></p>
{% comment %}
<p><a href="{% url 'accounts:change_password' %}">Забыли пароль?</a></p>
{% endcomment %}
</div>
</div>
{% endblock %}
Далее нам необходимо поправить базовый шаблон для внедрения ссылок манипуляций с аккаунтом. В директории templates открываем файл base.html и заменяем следующим содержимым:
{% load static %}
<!DOCTYPE html>
<html lang="ru">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="author" content="{{ SITE_AUTHOR }}">
<title>{% block title %}{% endblock %} | {{ SITE_TITLE }}</title>
<!-- Bootstrap -->
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">
<link href="https://maxcdn.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css" rel="stylesheet" integrity="sha384-wvfXpqpZZVQGK6TAh5PVlGOfQNHSoD2xbE+QkPxCAFlNEevoEH3Sl0sibVcOQVnN" crossorigin="anonymous">
<!-- Style -->
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap-theme.min.css" integrity="sha384-rHyoN1iRsVXV4nD0JutlnGaslCJuC7uwjduW9SVrLvRYooPp2bWYgmgJQIXwl/Sp" crossorigin="anonymous">
<link href="https://fonts.googleapis.com/css?family=Open+Sans:400,700%7CUbuntu:700&subset=cyrillic" rel="stylesheet">
<link rel="stylesheet" href="{% static 'style.css' %}">
<!-- HTML5 shim and Respond.js for IE8 support of HTML5 elements and media queries -->
<!-- WARNING: Respond.js doesn't work if you view the page via file:// -->
<!--[if lt IE 9]>
<script src="https://oss.maxcdn.com/html5shiv/3.7.3/html5shiv.min.js"></script>
<script src="https://oss.maxcdn.com/respond/1.4.2/respond.min.js"></script>
<![endif]-->
<!-- jQuery (necessary for Bootstrap's JavaScript plugins) -->
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.4/jquery.min.js"></script>
<!-- Include all compiled plugins (below), or include individual files as needed -->
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js" integrity="sha384-Tc5IQib027qvyjSMfHjOMaLkfuWVxZxUPnCJA7l2mCWNIpG9mGCD8wGNIcPD7Txa" crossorigin="anonymous"></script>
</head>
<body>
<header>
<nav class="navbar navbar-default navbar-static-top">
<div class="container">
<ul class="nav navbar-nav navbar-right">
{% if user.is_authenticated %}
<li class="dropdown">
<a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false">
<i class="fa fa-user fa-fw" aria-hidden="true"></i>
{{ user.username }}
<span class="caret"></span>
</a>
<ul class="dropdown-menu">
{% comment %}
<li>
<a href="{% url 'accounts:change_password' %}">
<i class="fa fa-key fa-fw" aria-hidden="true"></i>
Смена пароля
</a>
</li>
<li>
<a href="{% url 'accounts:change_email' %}">
<i class="fa fa-envelope-o fa-fw" aria-hidden="true"></i>
Смена почты
</a>
</li>
{% endcomment %}
<li><a href="{% url 'accounts:logout' %}">
<i class="fa fa-sign-out fa-fw" aria-hidden="true"></i>
Выход
</a></li>
</ul>
</li>
{% else %}
<li>
<a href="{% url 'accounts:login' %}">
<i class="fa fa-sign-in fa-fw" aria-hidden="true"></i>
Войти
</a>
</li>
{% endif %}
</ul>
</div>
</nav>
<div class="container">
<div class="about">
<div class="row">
<div class="col-sm-8">
<h2 class="title"><a href="/">{{ SITE_TITLE }}</a></h2>
<h3 class="subtitle">{{ SITE_SUBTITLE }}</h3>
</div>
<div class="col-sm-4">
<address class="contacts">
<div class="mail">
<span class="sr-only">Адрес электронной почты</span>
<i class="fa fa-envelope-o fa-fw" aria-hidden="true"></i>
Почта
</div>
<div class="location">
<span class="sr-only">Местоположение</span>
<i class="fa fa-globe fa-fw" aria-hidden="true"></i>
Местоположение
</div>
</address>
</div>
</div>
<div class="description">
<p>
В течение десяти лет работы на крупных производственных предприятиях заполучил опыт создания служб с нуля,
по направлениям: охрана труда, пожарная, промышленная и экологическая безопасность.
</p>
<p>
Проведу для Вас полный аудит или разработаю комплекты документов по всем вышеперечисленным направлениям.
</p>
</div>
</div>
</div>
</header>
<main>
<div class="container">
{% block main %}{% endblock %}
</div>
</main>
</body>
</html>
Как и в шаблоне входа здесь присутствуют закомментированные ссылки. Функционал для смены пароля и адреса электронной почты мы будем разрабатывать в следующей статье и соответственно данные строчки можно будет раскомментировать.