#32. Django Forms
Django Forms. Request, User, Authorization
План
- HTML форма
- GET
- POST
- Django Forms
- Валідація форми
- Модель User
- Ідентифікація, Аутентифікація, Авторизація
Форма призначена для обміну даними між користувачем і сервером.
Веб-форма - це набір текстових полів, списків, кнопок та інших елементів керування, за допомогою яких відвідувач сторінки може надати їй той чи інший вид інформації. Форми в Інтернеті всюди - завдяки формам ми можемо створювати облікові записи електронної пошти, переглядати і купувати товари в інтернет-магазинах, здійснювати фінансові транзакції та багато іншого. Найпростіша форма - це одиночне текстове поле пошукових систем
Тег <form> встановлює форму на веб-сторінці. Він “повідомляє” браузеру, що дані з цього тега потрібно згрупувати і підготувати до надсилання на сервер.
Приймає два параметри: action і method.
-
actionописує куди форма повинна оправити дані, в нашому випадку це будеurl, якщо не вказано явно, то форма буде відправлена на той самий урл, на якому зараз знаходиться. -
method- відповідає за метод запиту, варіанти цеgetіpost.getвикористовується за замовчуванням.
Post-форми використовуються для передачі даних, що не підлягають розголосу, наприклад, логін і пароль. Get-форми, використовуються для загальнодоступної інформації, наприклад рядок пошуку.
Усередині форми ми вказуємо потрібну кількість тегів <input> з потрібними типами. Саме ці дані будуть надалі передані серверу.
<form>
<label for="fname">First name:</label><br>
<input type="text" id="fname" name="fname"><br>
<label for="lname">Last name:</label><br>
<input type="text" id="lname" name="lname">
</form>
Основні типи інпутів
number - введення числа
text - введення тексту
checkbox - чекбокс (вибір декількох елементів через галочки)
radio - радіобаттон (вибір тільки одного елемента зі списку)
button - класична кнопка (якщо у формі є один такий елемент, але немає сабміту, браузер автоматично підрахує його сабмітом)
hidden - приховане поле, найчастіше потрібне для цілей безпеки або додавання інформації та даних, які не відображають її (Не відображається).
submit - надсилання форми
Це далеко не всі типи інпутів, які можуть бути. Посилання на типи інпутів
GET форма
Створимо найпростішу форму, для цього додамо url в urlpatterns, функцію в views.py для обробки і html сторінку в templates.
У urls.py
from .views import form_view
urlpatterns = [
path('form-url/', form_view, name='form-view'),
]
У views.py
def form_view(request):
return render(request, 'form.html')
У form.html
{% extends 'base.html' %}
{% block content %}
<form method="get" action="{% url 'form-view' %}">
<label>
<input type="text" name="my_name">
</label>
<button type="submit">Send name</button>
</form>
{% endblock %}
Зверніть увагу, ми вказали get форму, екшеном є url, на цю саму сторінку, який обробляється нашою ж функцією form_view.
У формі у нас один input, якому ми вказали 2 атрибути type і name.
Атрибут name нам необхідний для того, щоб ми змогли обробити дані у view.
Також у нас є кнопкаsubmit, необхідна для того, що б відправити запит на сервер.
Під час натискання на кнопку формується і надсилається request.
Приблизно ось так виглядатиме наша сторінка, якщо зайти на адресу http://127.0.0.1:8000/form-url/:
request
Об’єкт request, той, який приймає першим параметром функції у views.py і його ж передаємо першим у функцію render. Навіщо він потрібен, і з чого він складається?
Навіщо потрібен. Потрібен для того, щоб обробляти будь-які призначені для користувача або службові дані, які були передані.
*Складається з переданих даних або файлів (якщо їх було передано), і службової інформації (інформація про користувача, метод запиту, про те, на який url був запит, з якого браузера, інша системна інформація).
Що буде після натискання кнопки Send name?
Буде сформовано GET (метод форми) запит усіма заповненими нами даними і відправлено на сервер.
Зверніть увагу на новий url.

my_name - це попередньо вказаний атрибут name на нашій формі, а user значення, яке я передав у цей input.
У разі GET запиту дані передаються явно, прямо в url у вигляді ключ-значення. Якби значень було б більше одного, вони були б з’єднані за допомогою символу & (наприклад, якби я додав ще й поле із зазначеним атрибутом name зі значенням age та заповнив би його значенням 32, то url після запиту мав би такий вигляд /form-url/?my_name=Artem&age=32. Ніякої різниці між заповненням форми, або записом цих даних руками прямо в рядку браузера для GET запиту немає.
Обробка даних у view
Ми можемо обробити дані у view, за допомогою змінної request, дані з GET запиту, знаходитимуться у змінній request.GET.
дані знаходяться у вигляді словника, де ключами є атрибут name у кожному інпуті форми.
Ці дані можна використовувати для будь-яких цілей, але найчастіше через GET передаються дані по фільтрації, або додаткові параметри відображення, наприклад, коли ви додаєте фільтри в інтернет магазині, пишете текст в пошуку, або коли на ютубі пересилаєте посилання з таймкодом, воно теж передається як GET параметр.
POST запит
Давайте замінимо метод нашої форми з get на post:
У form.html:
{% extends 'base.html' %}
{% block content %}
<form method="post" action="{% url 'form-view' %}">{
<label>
<input type="text" name="my_name">
</label>
<button type="submit">Send name</button>
</form>
{% endblock %}
Що станеться під час надсилання такого запиту?
Відбудеться помилка, приблизно ось така:
Це помилка CSRF токена.
CSRF (англ. cross-site request forgery - “міжсайтова підробка запиту”) - вид атак на відвідувачів вебсайтів, що використовує недоліки протоколу HTTP. Якщо жертва заходить на сайт, створений зловмисником, від її особи таємно надсилається запит на інший сервер (наприклад, на сервер платіжної системи), який здійснює якусь шкідливу операцію (наприклад, переказ грошей на рахунок зловмисника). Для здійснення цієї атаки жертва має бути автентифікована на тому сервері, на який надсилається запит, і цей запит не повинен вимагати будь-якого підтвердження з боку користувача, яке не може бути проігноровано або підроблено атакувальним скриптом.
Щоб зрозуміти, що таке CSRF токена, потрібно розуміти різницю того, де використовуються різні запити.
GET запити, це запити загальнодоступні та інформаційні, відкрити сторінку, відфільтрувати дані ітд.
POST запити, це запити з чутливими даними, створення записів у базі, передача пароля, надсилання грошей з рахунку на рахунок, ітд.
Так от, якщо GET запит надіслати 5 разів поспіль, то з погляду сервера нічого не зміниться, ви просто 5 разів поспіль запитаєте одну й ту саму інформацію.
Якщо змінити параметри, то теж нічого страшного не станеться, просто запитаються інші дані.
А ось якщо повторити кілька разів або підробити дані в POST запиті, то можна здійснити різні проблемні дії, створення зайвих записів у базі даних, або переказ коштів на рахунок зловмисників замість очікуваного, тощо.
Тому в Django спочатку є додаткова вимога до POST форм, це ще одне приховане поле, заздалегідь згенероване сервером. Воно називається CSRF токен, де воно перевіряється і чому ми бачимо помилку, ми розберемо на наступних заняттях.
Для того що б додати потрібний токен, використовується спеціальний темплейт тег {% csrf_token %}, його потрібно додати в будь-якому місці всередині тега <form>.
{% extends 'base.html' %}
{% block content %}
<form method="post" action="{% url 'form-view' %}">
{% csrf_token %}
<label>
<input type="text" name="my_name">
</label>
<button type="submit">Send name</button>
</form>
{% endblock %}
Що зміниться з точки зору html:
<html lang="en"><head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div style="background-color: aqua">
<form method="post" action="/form-url/">
<input type="hidden" name="csrfmiddlewaretoken" value="Lr9N7x9yZaksWqLpz5GXgqiiSOAgc4kCkRCGW0A5bas9mc50H87PMAqW1Jdu7iBy">
<input type="text" name="my_name">
<button type="submit">Send name</button>
</form>
</div>
</body>
</html>
З’явилося поле типу hidden, це означає, що воно не буде відображатися, але ці дані все одно потраплять на сервер. Це часто використовується, коли вам потрібно передати дані, які в тебе вже є під час відтворення, але їх не видно явно, припустімо, якщо ми пишемо коментар до коментаря, то щоб грамотно його створити, нам потрібен id батька, його зазвичай і передають як hidden філд.
Тепер наш запит відправиться успішно.
Зверніть увагу, урл не зміняться!
Тому що дані, відправлені через POST, не повинні бути загальнодоступними.
Обробка у view
Обробити дані з POST запиту, можна точно так само, дані будуть перебувати в змінній request.POST, якщо це просто дані і в request.FILES, якщо були передані файли.
Зверніть увагу, що разом із нашими даними був переданий і csrf токен. Зазвичай під час опрацювання даних він не потрібен, але дані було передано, а отже вони прийдуть на сервер.
Django Forms
Джанго надає нам можливість генерувати html форми з коду на python!
Що для цього потрібно. Створимо в нашому додатку файл forms.py
Усередині цього файлу вкажемо.
forms.py
from django import forms
class MyForm(forms.Form):
nickname = forms.CharField(label='My nickname', max_length=100)
age = forms.IntegerField(label='My age')
Оброблювач для урла замінимо на:
У views.py замінимо нашу функцію на:
from django.shortcuts import render
from .forms import MyForm
def form_view(request):
# if this is a POST request we need to process the form data
if request.method == 'POST':
# create a form instance and populate it with data from the request:
form = MyForm(request.POST)
# check whether it's valid:
if form.is_valid():
# process the data in form.cleaned_data as required
# some actions
return render(request, 'form_was_valid.html')
# if a GET (or any other method) we'll create a blank form
else:
form = MyForm()
return render(request, 'form.html', {'form': form})
Не забуваємо імпортувати форму
Змінимо файл form.html:
{% extends 'base.html' %}
{% block content %}
<form method="post" action="{% url 'form-view' %}">
{% csrf_token %}
{{ form }}
{# Інпути були замінені на змінну, в якій лежить об'єкт класу Form #}
<button type="submit">Send form</button>
</form>
{% endblock %}
і створимо файл form_was_valid.html:
{% extends 'base.html' %}
{% block content %}
<div style="background-color: deeppink"> FORM WAS VALID</div>
<a href="{% url 'form-view' %}">To the form page</a>
{% endblock %}
Що саме ми зробили.
Опис форми
У файлі forms.py ми створили клас форми, в якому описали два атрибути nickname і age.
Вони відповідатимуть двом інпутам, текстовому і числовому.
Типів існує природно набагато більше
Основні типи:
BooleanField - булеан
CharField - текст
ChoiceField - поле для вибору
DateTimeField - дата час
EmailField - імейл
FileField - файл
IntegerField - ціле число
MultipleChoiceField - множинний вибір
І багато інших, почитати про них потрібно тут
У кожного поля є додаткові параметри
Агрументи полів:
required - чи є поле обов’язковим
label - лейбл, текст до інпуту
label_suffix - символ між лейблом та інпутом
initial - значення за замовчуванням
widget - описано нижче
help_text - підказка до інпуту
error_messages - переписати стандартні тексти для помилок типів полів
validators - додаткові перевірки поля
localize - інформація про переведення форми іншими мовами
disabled - зробити поле не активним (без можливості зміни)
Детальніше тут
Widgets
У полів форми є таке поняття як віджет, він відповідає за те, як саме буде відображатися конкретний філд, наприклад, для тексту базово це текстове поле, а для дати і часу, це вбудований пікер (вікно з календарем і годинником, яке випадає назовні) тощо.
Віджет можна вказати відмінний від стандартного.
Прочитати про віджети тут.
Опис view
У змінній request зберігається інформація про те, який саме тип запиту до нас прийшов, а це значить, що простим if ми можемо розмежувати логіку, яка оброблятиме різні типи запитів.
Якщо ми просто відкриваємо сторінку в браузері, то насправді ми посилаємо звичайний GET запит.
Поглянемо на код. Під час GET запиту, ми не потрапляємо в першу умову, змінній form призначаємо об’єкт класу MyForm без будь-яких даних, і після цього рендеруємо сторінку передавши на сторінку порожній об’єкт класу форми.
Під час рендерингу об’єкта класу форми в шаблоні, цей об’єкт перетворюється на набір інпутів, з уже зазначеними атрибутами name.
Якщо ми заповнимо дані, і натиснемо на кнопку Send form, то ми відправимо за цим же урлом запит, але вже типу POST із заповненими даними.
Подивимося в код ще раз, ми потрапимо в перший if, і змінній form призначимо об’єкт класу MyFrom, але попередньо, передавши туди дані через request.POST.
А отже, на цьому етапі в нас є об’єкт із даними, переданими нам від клієнта.
Дані які ми отримали з реквесту завжди потрібно валідувати (перевіряти)
Валідація форми
Тут уся документація з валідації.
За валідацію даних у формі відповідає вбудований метод is_valid() який застосовується до об’єкта класу форми.
Цей метод повертає нам булеве значення, True якщо дані валідні, False якщо ні.
Після виклику цього методу у змінної до якої він був викликаний (у нашому випадку змінна form) з’являються додаткові атрибути
Якщо форма була валідна, то з’являється додатковий атрибут cleaned_data, це словник, у якому зберігатимуться всі дані, що надіслав нам користувач (наприклад, логін і пароль).
Якщо форма не була валідна, то з’являється додатковий атрибут errors, який зберігає в собі інформацію про помилки конкретних полів, або загальні помилки.
Цей атрибут одразу зберігає інформацію як відображати ці помилки в шаблоні, якщо вони існують
Валідність
Що ж узагалі таке валідність?
Валідність це відповідність заданим критеріям. Наприклад, якщо ми очікуємо, що нам надішлють вік, і ми очікуємо цифру, але нам надсилають букву, це означає, що дані не валідні.
Деякі поширені види валідацій можна вказати як атрибут поля форми, наприклад, максимальну довжину для рядка, або максимальне і мінімальне значення для числа.
clean_field
Якщо ми викликаємо метод is_valid() ми перевіряємо всі описані валідації. Але де вони описані, і чи можемо ми додати свої?
Описані вони в класі форми, і так ми можемо додати свої.
Усі базові валідації були описані під час створення полів.
Але припустимо, ми вважаємо, що для нашої форми валідним є тільки парний вік, як нам це перевірити?
Для перевірки конкретного поля, у формі класу потрібно вказати метод, який починатиметься зі слова clean_ і після цього назву поля, яке ми валідуємо.
Усі дані лежатимуть в атрибуті self.cleaned_data.
Якщо значення валідне, то метод має повертати значення цього атрибута.
Якщо значення не валідне, то метод має рейзити помилку ValidationError з описом помилки, яка пізніше відображатиметься на html.
У forms.py:
from django import forms
from django.core.exceptions import ValidationError
class MyForm(forms.Form):
nickname = forms.CharField(label='My nickname', max_length=100)
age = forms.IntegerField(label='My age')
def clean_age(self):
age = self.cleaned_data.get('age')
if not age % 2:
raise ValidationError('Age should be odd')
return age
clean
А що робити, якщо потрібно перевірити відповідність даних між собою, наприклад, що користувач не використовував свій вік як частину свого нікнейму?
Для цього ми можемо використовувати метод clean, в якому можемо виконати будь-які необхідні нам перевірки.
Для виконання всіх базових перевірок зазвичай використовується super
У forms.py
from django import forms
from django.core.exceptions import ValidationError
class MyForm(forms.Form):
nickname = forms.CharField(label='My nickname', max_length=100)
age = forms.IntegerField(label='My age')
def clean_age(self):
age = self.cleaned_data.get('age')
if not age % 2:
raise ValidationError('Age should be odd')
return age
def clean(self):
cleaned_data = super().clean()
age = cleaned_data.get('age')
nickname = cleaned_data.get('nickname')
if str(age) in nickname:
raise ValidationError('Age cannot be in nickname')
Метод clean нічого не повертає, це нормально :)
Якщо під час перевірки у вас може бути більше однієї помилки, то raise вам не підходить.
Для цього може використовуватися метод класу форми add_error, що приймає два параметри, назву поля, до якого відноситься помилка (може бути None, якщо помилка не відноситься до якогось поля, наприклад, неправильний юзернейм і/або пароль.
У forms.py:
from django import forms
from django.core.exceptions import ValidationError
class MyForm(forms.Form):
nickname = forms.CharField(label='My nickname', max_length=100)
age = forms.IntegerField(label='My age')
def clean_age(self):
age = self.cleaned_data.get('age')
if not age % 2:
raise ValidationError('Age should be odd')
return age
def clean(self):
cleaned_data = super().clean()
age = cleaned_data.get('age')
nickname = cleaned_data.get('nickname')
if str(age) in nickname:
self.add_error('age', 'Age cannot be in nickname')
self.add_error(None, 'This form always incorrect')
Відображення форми в шаблоні.
Отже, якщо наша форма була валідна, то ми відрендерили взагалі іншу сторінку, але якщо все ж таки була не валідна, то ми відрендеримо форму, в якої є атрибут errors, помилки одразу ж будуть відмальовані.
Так само у нас є способи по різному відмальовувати форми:
У об’єкта форми є стандартні поля і методи, які ми можемо вказувати в шаблоні, наприклад.
{{ form.as_table }} - рендер у вигляді таблиці
<form action = "" method = "post">
{% csrf_token %}
<table>
{{ form.as_table }}
</table>
<input type="submit" value="Submit">
</form>
{{ form.as_p }} - рендер кожного поля як параграфу через <p> тег
<form action = "" method = "post">
{% csrf_token %}
{{ form.as_p }}
<input type="submit" value=Submit">
</form>
{{ form.as_ul }} - рендер у вигляді списку через <li> теги
<form action = "" method = "post">
{% csrf_token %}
<ul>
{{ form.as_ul }}
</ul>
<input type="submit" value="Submit">
</form>
Також, можна рендерувати форму не цілком, а наприклад, за окремими філдами, за допомогою стандартного звернення через крапку, наприклад {{ form.name }}
У кожного поля є атрибут errors, який зберігає інформацію про помилки за цим полем, якщо вони були виявлені. {{ form.my_field.errors }}
Якщо запустити форму через for в ітерованому об’єкті будуть поля.
{% for field in form %}
<div class="fieldWrapper">
{{ field.errors }}
{{ field.label_tag }} {{ field }}
{% if field.help_text %}
<p class="help">{{ field.help_text|safe }}</p>
{% endif %}
</div>
{% endfor %}
І багато інших атрибутів і методів, детально можна прочитати тут
Методи та властивості моделі User
Модель User
Django надає нам вбудовану модель юзера, у якої вже реалізовано багато полів і методів
Документація про юзера тут
class User(AbstractUser):
"""
Users within the Django authentication system are represented by this model.
Username and password are required. Other fields are optional.
"""
class Meta(AbstractUser.Meta):
swappable = 'AUTH_USER_MODEL'
Стандартний юзер містить у собі такі корисні поля як:
username
password
email
first_name
last_name
is_active
is_staff
is_superuser
Також містить багато системних полів.
Також містить базовий метод set_password та інформацію про групи доступу.
Для використання моделі користувача, яку нам потрібно розширити (а це потрібно майже завжди) використовується успадкування від базового абстрактного юзера.
Виглядає приблизно так:
from django.contrib.auth.models import AbstractUser
from django.db import models
class MyUser(AbstractUser):
birth_date = models.DateField()
avatar = models.ImageField(blank=True, null=True)
Для того, щоб Django оцінювала цю модель як користувача, вsettings.py потрібно в будь-якому місці вказати:
AUTH_USER_MODEL = 'myapp.MyUser'
Де myapp - назва програми, MyUser - назва моделі.
Юзер обов'язково має бути описаний до першої міграції!!! Інакше джанго автоматично буде використовувати базового вбудованого юзера, і використовувати відразу кілька у вас не вийде. (Це працює тому що якщо не переписати модель і налаштування, то юзер, який вже є в базі даних, матиме таблицю, і її не можна буде перевизначити під іншу модель після)
Усі можливі подробиці про модель юзера тут
Крім стандартних полів юзер містить у собі інформацію про групи, до яких входить користувач, про користувацькі права, містить два поля статусу is_staff і is_superuser, найчастіше стафф - це співробітники, яких можна занести до адмінки, але в них обмежені права, суперюзеру можна все, але завжди залежить від ситуації.
is_stuff - поле для визначення співробітника (припустимо співробітник магазину, який додає товари)
is_superuser - поле для визначення адміністратора (наприклад, може змінювати список співробітників, а найчастіше має практично необмежені параметри)
Також зберігає інфо про останній логін користувача і дату створення користувача.
Об’єкт юзера містить багато корисних методів
get_username() # отримати юзернейм
get_full_name() # отримати ім'я та прізвище через пробіл
set_password(raw_password) # встановити хешований пароль
check_password(raw_password) # перевірити пароль на правильність
set_unusable_password() # дозволити використовувати порожній рядок як пароль
email_user(subject, message, from_email=None, **kwargs) # надіслати користувачеві імейл
Наприклад:
from django.contrib.auth.models import User
u = User.objects.get(username='blabla')
u.check_password('some_cool_password') # True
І інші методи, що відповідають за доступи, групи ітд.
Менеджер користувача
Містить додаткові методи
User.objects.create_user(username, email=None, password=None, **extra_fields)
User.objects.create_superuser(username, email, password, **extra_fields)
create_user відрізняється від create тим, що create_user правильно задасть пароль, через set_password
Django не зберігає пароль у чистому вигляді, тільки хешованим
Логін
Насправді логін складається з декількох частин, давайте їх розглянемо
Ідентифікація, Аутентифікація, Авторизація
Ідентифікація (Identification) - це процедура розпізнавання суб’єкта за його ідентифікатором (простіше кажучи, це процес визначення конкретної особи за ім’ям, логіном або номером).
Наприклад, отримати конкретного користувача з бази.
Ідентифікатором може бути:
- номер телефону
- номер паспорта
- електронна пошта
- номер сторінки в соціальній мережі тощо.
Автентифікація (Authentication) - це процедура перевірки автентичності (користувача перевіряють за допомогою пароля, лист перевіряють за електронним підписом тощо)
Наприклад, перевірити логін і пароль на відповідність.
- Пароль - те, що ми знаємо (слово, PIN-код, код для замка, графічний ключ)
- Пристрій - те, що ми маємо (пластикова картка, ключ від замка, USB-ключ)
- Біометрика - те, що є частиною нас (відбиток пальця, портрет, сітківка ока)
Авторизація (Authorization) - це надання доступу до будь-якого ресурсу.
Наприклад, до електронної пошти.
Приклади авторизації:
- Відчинення дверей після провертання ключа в замку
- Доступ до електронної пошти після введення пароля
- Розблокування смартфона після сканування відбитка пальця
- Видача коштів у банку після перевірки паспорта та даних про ваш рахунок
Як це працює
Для того, щоб користувач міг авторизуватися на сайті, нам потрібні його вхідні дані і стандартні методи authenticate, login
Метод authenticate відповідає одразу за два процеси, автентифікації та ідентифікації, приймає, ім’я користувача і пароль, і якщо знаходить збіг то, повертає об’єкт користувача(моделі), якщо не знаходить, то повертає None.
Якщо нам повернувся об’єкт юзера, значить, що аутентифікацію пройдено, і користувач ідентифікований.
Login
Метод login приймає, реквест, і об’єкт моделі користувача і відповідає за процес авторизації, після цієї дії, у всіх наступних запитах, у змінній request буде зберігатися наш поточний користувач.
Тому стандартним способом, для авторизації є приблизно такий код:
У forms.py
from django.contrib.auth import authenticate
from django import forms
from django.utils.translation import gettext_lazy as _
class AuthenticationForm(forms.Form):
username = forms.CharField(max_length=254)
password = forms.CharField(label=_("Password"), widget=forms.PasswordInput)
def clean(self):
cleaned_data = super().clean()
username = cleaned_data.get('username')
password = cleaned_data.get('password')
if username and password:
self.user = authenticate(username=username, password=password)
if self.user is None:
raise forms.ValidationError(_('User does not exist'))
в view.py
from .forms import AuthenticationForm
from django.contrib.auth import login
def my_login(request):
# if this is a POST request we need to process the form data
if request.method == 'POST':
# create a form instance and populate it with data from the request:
form = AuthenticationForm(request.POST)
# check whether it's valid:
if form.is_valid():
# process the data in form.cleaned_data as required
# some actions
login(request, form.user)
return HttpResponseRedirect('/')
# if a GET (or any other method) we'll create a blank form
else:
form = AuthenticationForm()
return render(request, 'login.html', {'form': form})
Насправді, функціі у view можна спростити, не втративши при цьому розмежування на обробку post і get запитів:
def my_login(request):
form = AuthenticationForm(request.POST or None)
if form.is_valid():
login(request, form.user)
return HttpResponseRedirect('/')
return render(request, 'login.html', {'form': form})
Logout
Для виведення користувача з системи використовується метод logout, який приймає тільки реквест.
from django.contrib.auth import logout
def logout_view(request):
logout(request)
return HttpResponseRedirect('/') # Redirect to a success page.
Перевірка на те, що користувач уже зайшов у систему
У реквесті завжди є поле user, у якого завжди є атрибут is_authenticated, перевіряючи його, ми можемо визначати, чи є користувач авторизованим.
request.user.is_authenticated
Закрити сторінку від не залогіненого користувача
Для того, щоб не надавати доступ для не залогінених користувачів, існує два способи, для функціонально описаних в’ю це декоратор @login_required
from django.contrib.auth.decorators import login_required
@login_required
def my_view(request):
...
Він також може приймати посилання на сторінку логіна й автоматично відправляти на цю сторінку для не залогіненого користувача.
from django.contrib.auth.decorators import login_required
@login_required(login_url='/accounts/login/')
def my_view(request):
pass
У теплейтах user доступний через змінну user
{% if user.is_authenticated %}
{{ user.username }}
{% else %}
Anonymous
{% endif %}
Домашнє завдання / Практика:
-
Напишіть форму, в якій можна вказати ім’я, стать, вік і рівень володіння англійською (списком, що випадає), якщо введені дані - це хлопець, старший за 20-ти (включно), з рівнем англійської B2 вище, або дівчина, старша за 22-ох, з рівнем, вищим за B1, - перейти на сторінку, де буде написано, що ви нам підходите, або що не підходите, відповідно.
-
Написати сторінку логіна і логаута руками, перевіряємо, що все працює.
-
Написати сторінку для реєстрації (використовуємо
create_user, який автоматично викличеset_password)
Наступна сторінка має відкриватися тільки залогіненим користувачам -
Написати сторінку для зміни пароля. (Запитуємо поточний пароль 2 рази, і перевіряємо через
check_password, просвоюємо черезset_password) -
Написати сторінку з get формою, для пошуку за текстом ваших коментарів, відобразити всі знайдені часткові збіги, без урахування регістру.
-
Додати до пошуку за коментарями галочку, щоб при натиснутій галочці показувало тільки твої коментарі