Мой Django 3.0 Project использует вид по умолчанию Django Сброс пароля, поэтому в моем url.py:
path('password_reset', auth_views.PasswordResetView.as_view(), name='password_reset')
наблюдается странное поведение, потому что когда я запрашиваю сброс пароля, view отправляет много писем на указанный мной адрес электронной почты (скажем, 37 писем). Это произошло независимо от использования SendGrid или AWS SES, поэтому в представлении что-то не так.
Я исследовал и думаю, что проблема в классе PasswordResetForm , который представление использует для отправки электронных писем. Такая форма имеет метод get_users()
, который возвращает совпадающих пользователей, которые должны получить сброс, он извлекает всех активных пользователей, отправивших электронное письмо.
def get_users(self, email):
"""Given an email, return matching user(s) who should receive a reset.
This allows subclasses to more easily customize the default policies
that prevent inactive users and users with unusable passwords from
resetting their password.
"""
email_field_name = UserModel.get_email_field_name()
active_users = UserModel._default_manager.filter(**{
'%s__iexact' % email_field_name: email,
'is_active': True,
})
return (
u for u in active_users
if u.has_usable_password() and
_unicode_ci_compare(email, getattr(u, email_field_name))
)
Метод save()
формы отправляет электронное письмо каждому из пользователей, возвращенных get_users()
. Я думаю, что моя проблема в том, что я зарегистрировал несколько пользователей (скажем, 37) с одним и тем же адресом электронной почты (поскольку Django позволяет это по умолчанию), и теперь метод сохранения отправляет по одному сообщению электронной почты для каждого из этих пользователей на адрес электронной почты адрес.
def save(self, domain_override=None,
subject_template_name='registration/password_reset_subject.txt',
email_template_name='registration/password_reset_email.html',
use_https=False, token_generator=default_token_generator,
from_email=None, request=None, html_email_template_name=None,
extra_email_context=None):
"""
Generate a one-use only link for resetting password and send it to the
user.
"""
email = self.cleaned_data["email"]
if not domain_override:
current_site = get_current_site(request)
site_name = current_site.name
domain = current_site.domain
else:
site_name = domain = domain_override
email_field_name = UserModel.get_email_field_name()
for user in self.get_users(email):
user_email = getattr(user, email_field_name)
context = {
'email': user_email,
'domain': domain,
'site_name': site_name,
'uid': urlsafe_base64_encode(force_bytes(user.pk)),
'user': user,
'token': token_generator.make_token(user),
'protocol': 'https' if use_https else 'http',
**(extra_email_context or {}),
}
self.send_mail(
subject_template_name, email_template_name, context, from_email,
user_email, html_email_template_name=html_email_template_name,
)
Мой вопрос: действительно ли это желательное поведение по умолчанию для Django? и как можно исправить отправку только одного электронного письма при сбросе пароля, независимо от того, сколько пользователей зарегистрировано с одним и тем же адресом электронной почты?