如何在Django allauth注册流程中用激活码替代确认链接?
我之前刚好做过类似的需求——把Django allauth默认的邮件链接确认改成验证码输入验证,适配REST API场景。下面是我整理的具体实现步骤,亲测可行:
实现Django allauth注册流程:用验证码代替邮件确认链接
1. 自定义账号适配器,替换验证码生成与邮件发送逻辑
allauth默认生成的是哈希风格的确认链接key,我们需要把它改成6位随机数字验证码,同时替换邮件内容为发送验证码而非链接。
创建一个自定义适配器文件(比如yourapp/adapters.py):
from allauth.account.adapter import DefaultAccountAdapter import random import string class CustomAccountAdapter(DefaultAccountAdapter): def generate_key(self): # 生成6位随机数字验证码 return ''.join(random.choices(string.digits, k=6)) def send_confirmation_mail(self, request, emailconfirmation, signup): # 构建邮件上下文,传入验证码 ctx = { "user": emailconfirmation.email_address.user, "code": emailconfirmation.key, # 这里就是我们生成的6位验证码 } # 使用自定义的邮件模板发送验证码 self.send_mail( "account/email/email_confirmation_signup_code", emailconfirmation.email_address.email, ctx, )
然后在项目settings.py中配置使用这个适配器:
ACCOUNT_ADAPTER = 'yourapp.adapters.CustomAccountAdapter'
2. 编写自定义验证码邮件模板
在项目的templates/account/email/目录下创建两个模板文件(纯文本和HTML版本,按需选择):
email_confirmation_signup_code.txt(纯文本模板):
您好,{{ user.username }}! 您的账号激活验证码是:{{ code }} 请在应用的激活页面输入此验证码完成账号验证,验证码15分钟内有效。 如果您没有注册过我们的账号,请忽略此邮件。
email_confirmation_signup_code.html(HTML模板,可选):
<p>您好,{{ user.username }}!</p> <p>您的账号激活验证码是:<strong>{{ code }}</strong></p> <p>请在应用的激活页面输入此验证码完成账号验证,验证码15分钟内有效。</p> <p>如果您没有注册过我们的账号,请忽略此邮件。</p>
3. 开发REST API的验证码验证接口
因为是REST API场景,需要写一个DRF视图来处理用户提交的邮箱和验证码,验证通过后激活账号:
from rest_framework.views import APIView from rest_framework.response import Response from rest_framework import status from allauth.account.models import EmailConfirmation, EmailAddress from django.core.exceptions import ObjectDoesNotExist from django.utils import timezone class VerifyActivationCodeAPIView(APIView): def post(self, request): email = request.data.get('email') code = request.data.get('code') if not email or not code: return Response( {"error": "邮箱和验证码不能为空"}, status=status.HTTP_400_BAD_REQUEST ) try: email_address = EmailAddress.objects.get(email=email) email_confirmation = EmailConfirmation.objects.get( email_address=email_address, key=code, confirmed=False ) # 验证验证码是否过期(这里设置15分钟有效期) if (timezone.now() - email_confirmation.created).total_seconds() > 900: return Response( {"error": "验证码已过期"}, status=status.HTTP_400_BAD_REQUEST ) # 确认邮箱,激活账号 email_confirmation.confirm(request) return Response( {"message": "账号激活成功"}, status=status.HTTP_200_OK ) except ObjectDoesNotExist: return Response( {"error": "验证码无效或邮箱未注册"}, status=status.HTTP_400_BAD_REQUEST )
在项目urls.py中添加该接口的路由:
from django.urls import path from .views import VerifyActivationCodeAPIView urlpatterns = [ # 其他路由... path('api/auth/verify-code/', VerifyActivationCodeAPIView.as_view(), name='verify_activation_code'), ]
4. 调整注册相关的全局配置(可选)
根据需求在settings.py中调整allauth的默认行为:
ACCOUNT_EMAIL_REQUIRED = True # 强制要求邮箱注册 ACCOUNT_AUTHENTICATION_METHOD = 'email' # 用邮箱作为登录凭证 ACCOUNT_LOGIN_ON_EMAIL_CONFIRMATION = True # 激活后自动登录 ACCOUNT_EMAIL_CONFIRMATION_EXPIRE_DAYS = 1 # 验证码有效期(这里全局设置1天,和接口里的15分钟可以配合)
额外优化建议
- 增加验证码重试次数限制:可以在用户模型添加
failed_verify_attempts字段,超过3次锁定10分钟 - 开发重新发送验证码接口:复用适配器的
send_confirmation_mail方法,给指定邮箱重新生成并发送新验证码 - 前端配合做倒计时:提示用户验证码剩余有效期,避免重复提交
内容的提问来源于stack exchange,提问作者robd
相关产品推荐
相关产品推荐

