Отправка писем с подтверждением регистрации
Вот классический сценарий:
- Вы создаете учетную запись.
- Вы указываете адрес электронной почты, который будет идентифицирован, как уникальный на платформе.
- Платформа проверяет, что вы действительно являетесь владельцем адреса электронной почты, отправив электронное письмо с ссылкой на подтверждение.
- Пока Вы не выполните проверку, вы не сможете (полностью) использовать платформу.
Давайте добавим флаг 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 ждет ответа, и только после этого он возвращает ответ на наш браузер.