如何在Django的UserCreationForm中设置is_active=False实现邮箱验证?
如何在Django注册时将用户is_active设为False并实现邮箱验证?
我来帮你搞定这个需求!默认的UserCreationForm创建用户时确实会把is_active设为True,我们只需要自定义表单覆盖这个行为,再配合邮箱验证逻辑就能实现你的目标。下面是一步步的实现方案:
1. 自定义用户注册表单
首先,我们需要继承UserCreationForm,重写它的save方法,把创建的用户is_active设为False。另外,默认的表单没有邮箱字段,我们也需要加上(毕竟要发验证邮件):
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') def save(self, commit=True): # 先不提交到数据库,拿到用户实例 user = super().save(commit=False) # 核心:把is_active设为False user.is_active = False # 保存用户输入的邮箱 user.email = self.cleaned_data['email'] if commit: user.save() return user
2. 创建邮箱验证模型(存储验证码/链接)
为了追踪用户的验证状态,我们需要一个模型来存储验证token和关联的用户,还可以设置过期时间提升安全性:
from django.db import models from django.contrib.auth.models import User import uuid from django.utils import timezone from datetime import timedelta class EmailVerification(models.Model): user = models.OneToOneField(User, on_delete=models.CASCADE, related_name='verification') # 用UUID生成唯一验证token token = models.UUIDField(default=uuid.uuid4, editable=False) created_at = models.DateTimeField(auto_now_add=True) # 设置24小时过期 expires_at = models.DateTimeField(default=lambda: timezone.now() + timedelta(hours=24)) def is_expired(self): return timezone.now() > self.expires_at
3. 编写注册视图:处理表单+发送验证邮件
在注册视图里,我们处理表单提交,创建未激活的用户,生成验证token,然后发送包含验证链接的邮件:
from django.shortcuts import render, redirect from django.core.mail import send_mail from django.contrib import messages from .forms import CustomUserCreationForm from .models import EmailVerification def register(request): if request.method == 'POST': form = CustomUserCreationForm(request.POST) if form.is_valid(): # 创建未激活的用户 user = form.save() # 生成验证记录 EmailVerification.objects.create(user=user) # 构建验证链接 verification_url = f"{request.scheme}://{request.get_host()}/verify/{user.verification.token}/" # 发送验证邮件 send_mail( subject='完成你的账号注册验证', message=f"点击下面的链接激活你的账号:\n{verification_url}\n链接24小时内有效", from_email='你的邮箱地址@example.com', recipient_list=[user.email], fail_silently=False, ) messages.success(request, '注册成功!请检查你的邮箱,点击验证链接激活账号') return redirect('login') # 跳转到登录页面 else: form = CustomUserCreationForm() return render(request, 'registration/register.html', {'form': form})
4. 编写验证视图:激活用户
接下来写处理验证链接的视图,验证token的有效性,然后把用户的is_active设为True:
from django.shortcuts import get_object_or_404, redirect from django.contrib import messages from .models import EmailVerification def verify_email(request, token): # 根据token找到验证记录 verification = get_object_or_404(EmailVerification, token=token) # 检查链接是否过期 if verification.is_expired(): messages.error(request, '验证链接已过期,请重新注册') verification.delete() return redirect('register') # 激活用户 user = verification.user user.is_active = True user.save() # 验证完成后删除记录 verification.delete() messages.success(request, '邮箱验证成功!现在可以登录你的账号了') return redirect('login')
5. 配置URL路由
最后,把注册和验证的视图添加到URL配置里:
from django.urls import path from . import views urlpatterns = [ path('register/', views.register, name='register'), path('verify/<uuid:token>/', views.verify_email, name='verify_email'), # 其他路由... ]
额外注意事项
- 记得在
settings.py里配置好邮件发送参数,比如SMTP服务器信息,否则邮件发不出去:EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend' EMAIL_HOST = 'smtp.example.com' # 比如smtp.gmail.com EMAIL_PORT = 587 EMAIL_USE_TLS = True EMAIL_HOST_USER = '你的邮箱账号' EMAIL_HOST_PASSWORD = '你的邮箱密码/授权码' - 如果你用的是自定义用户模型,只需要把代码里的
User换成你的自定义模型类即可,表单和模型关联也要对应调整。 - 可以给验证逻辑添加更多安全校验,比如检查用户是否已经被激活,避免重复验证。
内容的提问来源于stack exchange,提问作者Md. Mizanur Rahman Khan
相关产品推荐
相关产品推荐

