You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

使用一次性令牌的激活URL无法访问,如何正确编码user.pk?

解决Django激活链接中URL编码导致的404问题

这个问题我之前做Django用户激活功能时也碰到过!核心原因是你生成的uid字节对象,而不是字符串,模板渲染时会把字节的字面表示(比如b'NjA')转义成URL里的特殊字符,最终导致链接被截断,触发404错误。

问题根源

urlsafe_base64_encode(force_bytes(user.pk))在Python 3中返回的是字节类型(bytes),当你把这个字节对象传入模板上下文后,Django的模板系统会将其转换成它的repr字符串形式(也就是b'NjA'),其中的单引号和b标识会被HTML转义成',最终生成的URL就会变成你看到的b'NjA'这种异常格式,浏览器解析到特殊字符时就会截断URL。

修复方案

只需要把生成的字节对象解码成字符串即可,在urlsafe_base64_encode后面加上.decode()方法:

修改你的get_context_data函数中生成uid的行:

uid = urlsafe_base64_encode(force_bytes(user.pk)).decode()

完整修改后的函数代码:

def get_context_data(self, request, user, context=None):
    if context is None:
        context = dict()
    current_site = get_current_site(request)
    protocol = 'https' if request.is_secure() else 'http'
    token = token_generator.make_token(user)
    # 解码成字符串,避免字节对象的转义问题
    uid = urlsafe_base64_encode(force_bytes(user.pk)).decode()
    context.update({
        'domain': current_site.domain,
        'protocol': protocol,
        'site_name': current_site.name,
        'token': token,
        'uid': uid,
        'user': user,
    })
    return context

额外注意:激活视图的解码要对应

在处理激活请求的视图中,你需要保持解码逻辑一致,确保能正确解析这个uid

from django.utils.http import urlsafe_base64_decode
from django.utils.encoding import force_text

# 示例激活视图中的解码逻辑
uid = urlsafe_base64_decode(uid_str).decode()
# 或者用force_text(兼容Django旧版本)
uid = force_text(urlsafe_base64_decode(uid_str))
user = User.objects.get(pk=uid)

这样修改后,生成的激活URL就会是正常的格式(比如http://127.0.0.1:8000/user/activate/NjA/4t8-9fad2c2dc78ecf8a1228/),不会再有特殊字符转义的问题,浏览器也能正确解析整个链接了。

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

火山引擎 最新活动