Создание сайта на Django: Урок 29, регистрация с подтверждением по электронной почте в Django
avatar
7 | (offline)
❤️‍🔥Notehunter Developer
Добавлено:
Категория: Руководства «Django»
Комментариев: 0

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

Напоминаю, что перед чтением этого урока вам необходимо настроить SMTP в Django для отправки электронных писем.

Урок:

И так, для активации по email я хочу написать функцию под названием send_activate_email_message. Для этого, я создам в папке services файл email.py

В этом файле я и создам необходимую функцию:

modules/system/services/email.py

from django.contrib.auth.models import User
from django.contrib.sites.models import Site
from django.template.loader import render_to_string
from django.utils.encoding import force_bytes
from django.utils.http import urlsafe_base64_encode


from modules.system.services.utils import account_activation_token

def send_activate_email_message(email):
    user = User.objects.get(email=email)
    current_site = Site.objects.get_current().domain
    subject = 'Активация аккаунта на сайте Django блог'
    message = render_to_string('modules/system/authenticated/email/activate-mail.html', {
        'user': user,
        'domain': current_site,
        'uid': urlsafe_base64_encode(force_bytes(user.pk)),
        'token': account_activation_token.make_token(user),
    })
    return user.email_user(subject, message)

Пояснения:

  • В функцию мы передаем email при регистрации.
  • Получаем пользователя по данному email и отправляем ему письмо с токеном для активации.

Далее нам необходимо установить пакет six, для чего вы узнаете ниже:

pip install six
Collecting six
  Using cached six-1.16.0-py2.py3-none-any.whl (11 kB)
Installing collected packages: six
Successfully installed six-1.16.0

Отлично!

Но, нам нужно ещё написать функцию account_activation_token, для этого я напишу следующее в файле utils.py, что находится в модуле "system"

modules/system/services/utils.py

import six
from django.contrib.auth.tokens import PasswordResetTokenGenerator

class AppTokenGenerator(PasswordResetTokenGenerator):
    """
    Генерация токенов для активации
    """
    def _make_hash_value(self, user, timestamp):
        return six.text_type(user.is_active) + six.text_type(user.pk) + six.text_type(timestamp)


account_activation_token = AppTokenGenerator()

Пояснения:

  • Мы наследуемся от генератора токенов по восстановлению паролей.
  • Импортируем необходимый функционал из установленного выше пакета six.

А теперь приступим к модернизации нашего представления RegisterCreateView, которое мы создавали в уроке 24.

modules\system\views\authenticated.py

from modules.system.services.email import send_activate_email_message

class RegisterCreateView(SuccessMessageMixin, CreateView):
    """
    Представление регистрации на сайте с формой регистрации
    """
    form_class = UserRegisterForm
    success_url = reverse_lazy('home')
    template_name = 'modules/system/authenticated/register.html'
    success_message = 'Вы успешно зарегистрировались. Подтвердите ваш email адрес. Может попасть в папку СПАМ!'

    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        context['title'] = 'Регистрация на сайте'
        return context

    def form_valid(self, form):
        if form.is_valid():
            user = form.save(commit=False)
            user.is_active = False
            user.save()
            send_activate_email_message(user.email)
        return super().form_valid(form)

Пояснение:

  • Я добавил в метод проверки form_valid, что при регистрации мы пользователю не даем активированный аккаунт, который дается по умолчанию. 
  • И в конце я добавляю функцию, которую мы создали, чтобы послать токен для активации на email.
  • Изменил success_message = Вы успешно зарегистрировались. Подтвердите ваш email адрес. Может попасть в папку СПАМ!

Давайте создадим шаблон для письма activate-mail.html:

templates/modules/system/authenticated/email/activate-mail.html

{% autoescape off %}

Здравствуйте, {{ user.get_username }},

Для подтверждения регистрации на сайте Django блог, перейдите по ссылке ниже:

    https://{{ domain }}{% url 'activate' uidb64=uid token=token %}

Спасибо, что решили присоединиться к нам!

Команда сайта Django блог

{% endautoescape %}

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

Теперь мы должны создать представление обработки активации:

modules\system\views\authenticated.py

from django.utils.http import urlsafe_base64_decode
from django.utils.encoding import force_str
from django.views import View
from django.contrib.auth.models import User

from django.contrib.auth import login
from django.contrib import messages
from django.shortcuts import redirect

from modules.system.services.utils import account_activation_token

class ActivateAccountView(View):
    """
    Активация аккаунта на сайте по токену
    """

    def get(self, request, uidb64, token, *args, **kwargs):
        try:
            uid = force_str(urlsafe_base64_decode(uidb64))
            user = User.objects.get(pk=uid)
        except (TypeError, ValueError, OverflowError, User.DoesNotExist):
            user = None

        if user is not None and account_activation_token.check_token(user, token):
            user.is_active = True
            user.save()
            login(request, user)
            messages.success(request, 'Ваш аккаунт успешно подтвержден')
            return redirect('home')
        else:
            messages.warning(request, 'Ссылка на активацию аккаунта устарела или не работает')
            return redirect('home')

Пояснения:

  • Перейдя по сгенерированной ссылки из письма мы обрабатываем ее, проверяя по токену.
  • Активируем пользователя
  • Авторизуем пользователя 
  • Выводим успешное сообщение о подтверждении аккаунта
  • Редеректим его на главную

А теперь нужно подправить urls.py

modules/system/urls.py

from django.urls import path

from modules.system.views import ProfileView, ProfileEditView, RegisterCreateView, UserLoginView, \
    UserPasswordChangeView, UserForgotPasswordView, UserPasswordResetConfirmView, UserLogoutView, ActivateAccountView

urlpatterns = [
    path('user/edit/', ProfileEditView.as_view(), name='profile-edit'),
    path('user/<str:slug>/', ProfileView.as_view(), name='profile'),
    path('register/', RegisterCreateView.as_view(), name='register'),
    path('login/', UserLoginView.as_view(), name='login'),
    path('logout/', UserLogoutView.as_view(), name='logout'),
    path('password-change/', UserPasswordChangeView.as_view(), name='password-change'),
    path('password-reset/', UserForgotPasswordView.as_view(), name='password-reset'),
    path('set-new-password/<uidb64>/<token>/', UserPasswordResetConfirmView.as_view(), name='password-reset-confirm'),
    path('activate/<uidb64>/<token>/', ActivateAccountView.as_view(), name='activate'),
]

Пояснение:

  • Импортировал ActivateAccountView
  • Добавил activate/<uidb64>/<token>

Давайте попробуем зарегистрировать аккаунт и проверить активацию.

Теперь проверю свою почту. А вот и наше письмо активации:

Перейдем по ссылке:

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

Комментарии к статье 0
Комментариев нет
Форма добавления комментария (необходима регистрация)