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

如何在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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.28 10:16:54