You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Django创建账户时要求邮箱验证的实现方案咨询

问题描述

我有一个Django项目,需要用户创建账户以访问内容,目前使用UserCreationForm实现注册功能。我的views.py代码如下:

def register_user(request):
    if request.method == "POST":
        user_form = UserCreationForm(request.POST)
        if user_form.is_valid():
            new_user = user_form.save(commit=False)
            new_user.set_password(user_form.cleaned_data["password1"])
            new_user.save()
            template = "account/registration/registration_done.html"
            context = {"new_user": new_user}
        else:
            # TODO: Handle exception
            raise BaseException
    elif request.method == "GET":
        user_form = UserCreationForm()
        template = "account/registration/register.html"
        context = {"user_form": user_form}
    else:
        raise NotImplementedError
    return render(request, template, context=context)

对应的模板代码为:

{% extends "base.html" %}
{% block title %}Create an Account{% endblock %}
{% block content %}
<h1>Create an Account</h1>
<form action="." method="post">
    {{ user_form.as_p }}
    {% csrf_token %}
    <p><input type="submit" value="Create my account"></p>
</form>
{% endblock %}

当前功能可正常运行,但注册表单仅包含用户名、密码及密码确认字段,未要求用户输入有效邮箱。我希望添加必填邮箱字段,并发送邮件验证邮箱有效性及用户使用权,请问Django认证系统是否已有现成实现方案,还是需要自行编写表单及相关处理逻辑?


解决方案

好问题!Django本身提供了基础支持,但完整的邮箱验证流程需要补充部分逻辑;你也可以用成熟的第三方库快速实现,下面分两种情况详细说明:

方案一:基于Django原生工具自行实现

Django默认的User模型本身就带有email字段,只是UserCreationForm没把它加入表单。我们可以自定义表单添加邮箱字段,再补充验证流程:

1. 自定义注册表单

在你的app里新建forms.py,继承UserCreationForm并添加必填邮箱字段:

from django.contrib.auth.forms import UserCreationForm
from django.contrib.auth.models import User
from django import forms

class CustomUserCreationForm(UserCreationForm):
    email = forms.EmailField(required=True, help_text='必填项,请输入有效的邮箱地址。')

    class Meta:
        model = User
        fields = ('username', 'email', 'password1', 'password2')

2. 更新视图逻辑

修改register_user视图,用自定义表单替代原有的UserCreationForm,同时将用户设置为未激活状态(等邮箱验证后再激活):

def register_user(request):
    if request.method == "POST":
        user_form = CustomUserCreationForm(request.POST)
        if user_form.is_valid():
            new_user = user_form.save(commit=False)
            new_user.email = user_form.cleaned_data['email']
            new_user.set_password(user_form.cleaned_data["password1"])
            # 先设为未激活,验证邮箱后再激活账号
            new_user.is_active = False
            new_user.save()
            # 后续添加生成验证token和发送邮件的逻辑
            template = "account/registration/registration_done.html"
            context = {"new_user": new_user, "message": "请检查你的邮箱,点击激活链接完成注册"}
        else:
            # 替换抛异常逻辑,将表单错误返回给用户
            template = "account/registration/register.html"
            context = {"user_form": user_form}
    elif request.method == "GET":
        user_form = CustomUserCreationForm()
        template = "account/registration/register.html"
        context = {"user_form": user_form}
    else:
        raise NotImplementedError
    return render(request, template, context=context)

3. 实现邮箱验证逻辑

Django自带的PasswordResetTokenGenerator可以复用,用来生成安全的邮箱验证token:

第一步:创建token生成器

在app里新建tokens.py:

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

class AccountActivationTokenGenerator(PasswordResetTokenGenerator):
    def _make_hash_value(self, user, timestamp):
        # 用用户ID、时间戳和激活状态生成唯一哈希值
        return (
            six.text_type(user.pk) + six.text_type(timestamp) +
            six.text_type(user.is_active)
        )

account_activation_token = AccountActivationTokenGenerator()

第二步:发送验证邮件

回到视图,在new_user.save()后添加发送邮件的代码:

from django.core.mail import send_mail
from django.urls import reverse
from django.utils.http import urlsafe_base64_encode
from django.utils.encoding import force_bytes
from .tokens import account_activation_token

# 生成激活链接
activate_url = request.build_absolute_uri(
    reverse("activate", 
            kwargs={"uidb64": urlsafe_base64_encode(force_bytes(new_user.pk)), 
                    "token": account_activation_token.make_token(new_user)}))
subject = '请激活你的账号'
message = f'你好,{new_user.username}!请点击下面的链接激活你的账号:\n{activate_url}'
# 替换为你的发件邮箱
send_mail(subject, message, 'your-email@example.com', [new_user.email])

第三步:创建激活视图

在views.py里添加激活账号的视图:

from django.utils.http import urlsafe_base64_decode
from django.utils.encoding import force_text
from django.contrib.auth.models import User
from django.shortcuts import render, redirect
from .tokens import account_activation_token

def activate(request, uidb64, token):
    try:
        # 解码用户ID
        uid = force_text(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()
        return redirect('login')  # 跳转到登录页
    else:
        # 验证失败,返回错误页面
        return render(request, 'account/registration/activation_invalid.html')

第四步:添加激活路由

在项目的urls.py里添加激活链接的路由:

from django.urls import path
from . import views

urlpatterns = [
    # ... 其他路由
    path('register/', views.register_user, name='register'),
    path('activate/<uidb64>/<token>/', views.activate, name='activate'),
]

方案二:使用第三方库快速实现(推荐)

如果不想自己编写大量逻辑,推荐使用django-allauth这个成熟的库,它内置了邮箱注册、邮箱验证、社交登录等全套功能,配置简单:

1. 安装库

pip install django-allauth

2. 配置settings.py

在INSTALLED_APPS和相关配置中添加:

INSTALLED_APPS = [
    # ... 你的其他app
    'django.contrib.sites',
    'allauth',
    'allauth.account',
    'allauth.socialaccount',
]

AUTHENTICATION_BACKENDS = [
    'django.contrib.auth.backends.ModelBackend',
    'allauth.account.auth_backends.AuthenticationBackend',
]

SITE_ID = 1  # allauth必须配置此项

# 邮箱验证相关配置
ACCOUNT_EMAIL_REQUIRED = True  # 注册时必须填写邮箱
ACCOUNT_AUTHENTICATION_METHOD = 'email'  # 支持用邮箱登录
ACCOUNT_EMAIL_VERIFICATION = 'mandatory'  # 强制验证邮箱后才能登录
ACCOUNT_EMAIL_CONFIRMATION_EXPIRE_DAYS = 3  # 验证链接3天内有效

3. 添加路由

在项目的urls.py里添加allauth的路由:

from django.urls import path, include

urlpatterns = [
    # ... 其他路由
    path('accounts/', include('allauth.urls')),
]

配置完成后,allauth会自动处理注册时的邮箱必填、发送验证邮件、激活账号等流程,你只需创建对应模板(或直接使用默认模板)即可,省去大量自定义逻辑的工作。


内容的提问来源于stack exchange,提问作者Batman

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 03:37:55