Продвинутый Django 5 для продолжающих

Прогресс по курсу:  0/193

9.2 Подготовка проекта, добавление подтверждения регистрации
3 из 3 шагов пройдено

Отправка писем с подтверждением регистрации

Вот классический сценарий:

  • Вы создаете учетную запись.
  • Вы указываете адрес электронной почты, который будет идентифицирован, как уникальный на платформе.
  • Платформа проверяет, что вы действительно являетесь владельцем адреса электронной почты, отправив электронное письмо с ссылкой на подтверждение.
  • Пока Вы не выполните проверку, вы не сможете (полностью) использовать платформу.

Давайте добавим флаг is_verified и verify_uid в модель User:

import uuid


class User(AbstractBaseUser):
    email = models.EmailField(
        verbose_name='email address',
        max_length=255,
        unique=True,
    )
    first_name = models.CharField(verbose_name='first name', max_length=30, blank=True)
    last_name = models.CharField(verbose_name='last name', max_length=30, blank=True)
    is_active = models.BooleanField(default=True)
    is_admin = models.BooleanField(default=False)

    is_verified = models.BooleanField('verified', default=False) # new
    verification_uuid = models.UUIDField('Unique Verification UUID', default=uuid.uuid4)# new

    objects = UserAccountManager()
    USERNAME_FIELD = 'email'
    REQUIRED_FIELDS = ['first_name', 'last_name']

    def __str__(self):
        return self.email

    def has_perm(self, perm, obj=None):
        "Есть ли у пользователей конкретное разрешение?"
        return True

    def has_module_perms(self, app_label):
        "Есть ли у пользователя разрешения на просмотр приложения `app_label`?"
        return True

    @property
    def is_staff(self):
        "Явнается ли пользователь сотрудником?"
        # Самый простой ответ: Все администраторы - это сотрудники
        return self.is_admin


Давайте воспользуемся этим случаем, чтобы добавить возможность администрирования модели User:

from django.contrib import admin
from .models import User


@admin.register(User)
class UserAdmin(admin.ModelAdmin):
    pass


Не забываем после изменения модели выполнить миграции.

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

Сигналы срабатывают до/после определенных событий в приложении. Мы можем определить коллбеки, которые вызываются автоматически при срабатывании сигналов. Чтобы сделать триггер для коллбека, мы должны сначала подключить его к сигналу.

Мы собираемся создать коллбек, который будет вызван после создания пользователя. Мы добавим этот код после определения модели User в: main/models.py

from django.db.models import signals
from django.core.mail import send_mail
from django.urls import reverse


def user_post_save(sender, instance, signal, *args, **kwargs):
    if not instance.is_verified:
        send_mail(
            'Verify your  account',
            'Follow this link to verify your account: '
            'http://localhost:8000%s' % reverse('verify', kwargs={'uuid': str(instance.verification_uuid)}),
            'admin@localhost.ru',
            [instance.email],
            fail_silently=False,
        )

signals.post_save.connect(user_post_save, sender=User)


Здесь мы определили функцию user_post_save и связали ее с сигналом post_save (который запускается после сохранения модели), отправленным моделью User.

Django не отправляет электронные письма самостоятельно, его необходимо связать с почтовой службой. Для простоты вы можете добавить свои учетные данные Gmail в settings.py или добавить своего любимого поставщика электронной почты. Как создать свой аккаунт в Gmail для отправки писем, мы рассмотрели в первом курсе, в разделе 7.4. Если вы начали этот курс, не проходя предыдущий, то следуйте инструкции - https://support.google.com/accounts/answer/185833.


Вот как выглядит конфигурация для Gmail:

EMAIL_USE_TLS = True
EMAIL_HOST = 'smtp.gmail.com'
EMAIL_HOST_USER = 'my-email@gmail.com'
EMAIL_HOST_PASSWORD = 'xxxxxxxxxxxxxx'
EMAIL_PORT = 587


Следующим шагом нам необходимо выполнить проверку учетной записи, для этого в main/views.py добавим:

from django.shortcuts import render
from django.http import Http404
from .models import User


def verify(request, uuid):
    try:
        user = User.objects.get(verification_uuid=uuid, is_verified=False)
    except User.DoesNotExist:
        raise Http404("User does not exist or is already verified")

    user.is_verified = True
    user.save()
    return render(request, 'activate.html')


Добавим эти представления в: django_celery/urls.py:

from django.contrib import admin
from django.urls import path, include
from publish.views import view_post
from main.views import verify

urlpatterns = [
    path('admin/', admin.site.urls),
    path('<slug:slug>/', view_post, name='view_post'),
    path('verify/<uuid>', verify, name='verify'),
]


Кроме того, не забудьте создать файл templates/activate.html в каталоге шаблонов:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Accounts Activate</title>
</head>
<body>
    Accounts Activate
</body>
</html>

Мы его создали просто пустым шаблоном.

Проверим работу нашего проекта. Чтобы проверить все, зайдите в панель администратора и создайте нового пользователя с действительным адресом электронной почты:


Мы видим что наш пользователь успешно был создан:


Если вы все делали правильно, то вы получите электронное письмо со ссылкой для подтверждения:


Перейдя по этой ссылке мы попадаем на страницу подтверждения активации пользователя:


А затем проверите раздел администратора, Вы увидите, как была активирована учетная запись:


У нас есть проблема в текущей реализации. Возможно, вы заметили, что создание пользователя заметно медленное. Это происходит потому, что Django отправляет письмо с ссылкой на активацию во время запроса. 

Вот как это работает:

  • Мы отправляем пользовательские данные в приложение Django.
  • Приложение создает модель User, а затем создает соединение с Gmail(или другим выбранным вами почтовым сервисом).
  • Django ждет ответа, и только после этого он возвращает ответ на наш браузер.

  • Комментария
Будьте вежливы и соблюдайте наши принципы сообщества. Пожалуйста, не оставляйте решения и подсказки в комментариях, для этого есть отдельный форум.
Оставить комментарий

куда это добавлять не понятно (

 

Давайте добавим флаг is_verified и verify_uid в модель User:

import uuid


class User(AbstractBaseUser):
    email = models.EmailField(
        verbose_name='email address',
        max_length=255,
        unique=True,
    )
    first_name = model

@No_Name, в файл models.py приложения main.

Ошибка в publish/urls.py

@Anonymous_105352133, исправил, спасибо.