在我的项目中,我实现了电子邮件地址验证。
用户在表单中输入注册所需的所有数据,然后我们cleaned_data
从属性中获取电子邮件地址并发送消息。
我通过以下方式实现发送(我会在解释后附上代码):
- 有一个继承自 FormView 的 mixin,它定义了 FormValid 方法,以便将发送消息所需的数据发送到表单的 save 方法。
- 我们从上面的 mixin 中继承视图并定义随后在提交中使用的字段。
这是混合:
class SendsMessageMixin(FormView):
"""
A mixin that provides all inherited
classes with the functionality of sending an email.
"""
email_subject = email_template_name = token_generator = None
def form_valid(self, form):
"""
When this method is triggered, the data that will
later be used to send the message is passed to the form save method.
"""
form.save(
**
{
'request': self.request,
'use_https': self.request.is_secure(),
'subject': self.email_subject,
'template_name': self.email_template_name,
'token_generator': self.token_generator
}
)
return super().form_valid(form)
表现:
class Registration(UnauthorizedRequiredMixin, SendsMessageMixin):
form_class = ConsumerCreationForm
template_name = 'consumers/registration.html'
email_subject = 'Confirm your account.'
email_template_name = 'mail/verification.html'
token_generator = default_token_generator
success_url = reverse_lazy('message_sent')
表格保存方法:
def save(self, **sending_data):
"""
Saves an inactive user to the database, after sending
a message asking for confirmation of registration to the email address.
"""
consumer = super().save(commit=False)
consumer.set_password(self.cleaned_data['password'])
prepare_data_and_send_message_with_uid_and_token(consumer=consumer, **sending_data)
consumer.save()
return consumer
消息内容生成:
def prepare_data_and_send_message_with_uid_and_token(request, consumer, use_https, subject,
template_name, token_generator):
"""
Prepares data to be loaded into message content,
the main purpose of which is to send a unique link to the user.
"""
content = {
'domain': get_current_site(request).domain,
'uid': urlsafe_base64_encode(force_bytes(consumer.pk)),
'token': token_generator.make_token(consumer),
'protocol': 'https' if use_https else 'http'
}
send_message(subject, template_name, content, consumer.email)
发送消息
@task()
def send_message(subject, template_name, content, to_email):
"""
Sends a message to the specified email address in the background.
"""
body = render_to_string(template_name, content)
message = EmailMessage(subject, body, to=[to_email])
message.send()
huey用于后台发送
消息本身:
{% autoescape off %}
Hello, your email address has been selected for registration!
To confirm, follow the link.
{{ protocol }}://{{ domain }}{% url 'activate' uidb64=uid token=token %}
In case you didn't do it, just ignore this message.
{% endautoescape %}
切换到生成的激活链接时,会触发dispatch方法,由于方法在这里没有发挥作用,所以一般不重要。
在此调度方法中,我从 kwargs 字典中提取 uidb64 并使用以下构造:
urlsafe_base64_decode(uidb64).decode().
它返回无。
最重要的是,无论如何都会返回 None 。我想强调一下,uidb64 是完美生成的并进入了 kwargs。
我将添加一个我试图覆盖密码恢复表单的功能(以便在后台发送消息),当我转到生成的链接时,即 PasswordResetConfirmView 视图,使用现成的逻辑,一切一声巨响,我能够恢复该帐户的密码,因此uidb收到了我的帐户(解码工作没有返回None)。
我的回答:在任何情况下,urlsafe_base64_decode 函数都不能返回 None。
要么它在您的项目中的某个地方超载,要么是 python 本身的错误(这不太可能),或者是使用的 janga 版本的错误,或者你自己走错了路。
你在哪里看到没有?以及为什么您决定此特定函数返回 None 。请提供一个我们可以运行的示例代码,该代码将返回 None。然后就有可能争论。
问题是在注册表单的save方法中,也称为准备数据和发送消息的方法,我在将模型实例本身保存到数据库之前调用了它。如果检查,在发送消息之前,consumer.pk 等于 None,之后,当 save 方法起作用时,它有一个数值。感谢昵称 Mr. Fix 的人,他明确表示,如果您自己没有在那里发送 None,则永远不会返回 None。
总而言之,这只是交换两个操作的问题。