Регистрация пользователей на сайте

Курс по Django: https://stepik.org/a/183363

Архив проекта: lesson-19-coolsite.zip

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

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

логин; пароль; email; имя; фамилия

В частности, эту информацию можно посмотреть в панели администратора по адресу:

http://127.0.0.1:8000/admin/auth/user/

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

Вначале добавим ссылку для регистрации новых пользователей. Разместим ее рядом со ссылкой «Войти». Для этого в шаблоне base.html изменим код вывода для главного меню:

                            <ul id="mainmenu" class="mainmenu">
                            <li class="logo"><a href="{% url 'home' %}"><div class="logo"></div></a></li>
{% for m in menu %}
                            <li><a href="{% url m.url_name %}">{{m.title}}</a></li>
{% endfor %}
                            <li class="last">
                                      <a href="{% url 'register' %}">Регистрация</a> | <a href="{% url 'login' %}">Войти</a>
                            </li>
                            </ul>

Теперь, отдельно выводится последний пункт списка со ссылками на регистрацию и авторизацию. Далее, в файле utils.py в списке главного меню уберем последний пункт и добавим маршрут с именем register в список urlpatterns (файл urls.py):

path('register/', login, name='register'),

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

Следующим шагом добавим класс представления для регистрации. Сразу в маршруте пропишем:

path('register/', RegisterUser.as_view(), name='register'),

а в файле views.py добавим этот класс:

class RegisterUser(DataMixin, CreateView):
    form_class = RegisterUserForm
    template_name = 'women/register.html'
    success_url = reverse_lazy('login')
 
    def get_context_data(self, *, object_list=None, **kwargs):
        context = super().get_context_data(**kwargs)
        c_def = self.get_user_context(title="Регистрация")
        return dict(list(context.items()) + list(c_def.items()))

Так как мы работаем с формой, связанной с моделью для добавления новой информации, то используем базовый класс CreateView. Далее, указываем форму для регистрации пользователя UserCreationForm фреймворка Django, имя шаблона и адрес перенаправления при успешной регистрации. Все остальное вам здесь знакомо. Осталось добавить шаблон register.html:

{% extends 'women/base.html' %}
 
{% block content %}
<h1>{{title}}</h1>
 
<form method="post">
    {% csrf_token %}
    {{ form.as_p }}
    <button type="submit">Регистрация</button>
</form>
 
{% endblock %}

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

имя пользователя (логин); пароль; подтверждение пароля

Давайте улучшим внешний вид этой формы. Для этого нужно создать свой класс формы в файле forms.py. В базовом варианте его можно объявить так:

class RegisterUserForm(UserCreationForm):
    class Meta:
        model = User
        fields = ('username', 'password1', 'password2')

Здесь мы связываем форму со стандартной моделью User и прописываем обязательный атрибут fields для указания списка полей в форме. Откуда брать имена этих полей. Если открыть в админ панели зарегистрированного пользователя (root), то здесь через инспектора браузера можно посмотреть имена стандартных полей модели User. Именно их, затем, указываем в коллекции fields. Пока у нас только три поля.

Далее, в файле views.py в классе RegisterUser указываем форму RegisterUserForm. Все, если открыть страницу регистрации, то увидим ту же самую форму, но определенную через наш класс RegisterUserForm.

Следующее, что я бы хотел сделать – это назначить полям стили оформления. По идее, для этого существует атрибут widgets, который следовало бы прописать в классе Meta:

class RegisterUserForm(UserCreationForm):
    class Meta:
        model = User
        fields = ('username', 'password1', 'password2')
        widgets = {
            'username': forms.TextInput(attrs={'class': 'form-input'}),
            'password1': forms.PasswordInput(attrs={'class': 'form-input'}),
            'password2': forms.PasswordInput(attrs={'class': 'form-input'}),
        }

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

class RegisterUserForm(UserCreationForm):
    username = forms.CharField(label='Логин', widget=forms.TextInput(attrs={'class': 'form-input'}))
    password1 = forms.CharField(label='Пароль', widget=forms.PasswordInput(attrs={'class': 'form-input'}))
    password2 = forms.CharField(label='Повтор пароля', widget=forms.PasswordInput(attrs={'class': 'form-input'}))
...

Если теперь обновить страницу регистрации, то увидим три этих поля со стилями. Чтобы еще улучшить внешний вид, я сделаю вывод полей формы в шаблоне register.html через цикл (скопировано из addpage.html):

{% for f in form %}
<p><label class="form-label" for="{{ f.id_for_label }}">{{f.label}}: </label>{{ f }}</p>
<div class="form-error">{{ f.errors }}</div>
{% endfor %}

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

Давайте теперь добавим сюда еще одно поле email. Для этого в форме RegisterUserForm достаточно прописать атрибут:

email = forms.EmailField(label='Email', widget=forms.EmailInput(attrs={'class': 'form-input'}))

и указать его в коллекции:

fields = ('username', 'email', 'password1', 'password2')

Все, теперь пользователь должен вводить email при регистрации. Давайте зарегистрируемся. При успешной регистрации, мы автоматически перенаправляемся на страницу авторизации, как это и предусмотрено в классе представления RegisterUser. А в админ-панели появился еще один пользователь. Как видите, все достаточно просто.

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

https://docs.djangoproject.com/en/3.1/topics/auth/customizing/

Курс по Django: https://stepik.org/a/183363

Видео по теме