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

Django登录功能报错:'QuerySet' object has no attribute 'startswith'

问题分析与修复方案

你的登录验证报错'QuerySet' object has no attribute 'startswith',以及后续可能的密码验证失败,根源在两个地方:

1. 密码字段长度不足

你的User模型中user_password字段设置了max_length=20,但make_password()生成的哈希密码长度远超过20位,会被数据库截断,导致存储的哈希值不完整,后续验证必然失败。

2. 登录逻辑错误

你传给check_password()的第二个参数是QuerySet(User.objects.filter(...)返回的查询集合),但这个函数需要的是字符串类型的哈希密码,所以触发了类型错误。同时原本的逻辑完全没做密码验证,只要邮箱存在就直接登录,这是严重的安全问题。


第一步:修复模型的密码字段

修改user_password的长度为至少128位(Django默认密码字段长度):

class User(models.Model):
    user_email = models.CharField(primary_key=True, max_length=100)
    user_role_id = models.CharField(max_length=20)
    # 调整长度以容纳完整的哈希密码
    user_password = models.CharField(max_length=128)
    user_name = models.CharField(max_length=100)
    user_avatar_path = models.CharField(max_length=300)
    user_job_title = models.TextField(blank=True, null=True)
    user_educ_qual = models.TextField(blank=True, null=True)
    user_companies = models.TextField(blank=True, null=True)

    class Meta:
        managed = False
        db_table = 'user'

注意:因为设置了managed=False,修改模型后需要手动去数据库修改对应字段的长度,否则依然会截断哈希密码。

第二步:修复登录视图逻辑

重新梳理验证流程,先通过邮箱找到用户,再验证密码:

def user_login(request):
    if request.method == "POST":
        user_email = request.POST['user_email']
        user_password = request.POST['user_password']
        
        try:
            # 邮箱是主键,用get()获取单个用户对象
            user = User.objects.get(user_email=user_email)
        except User.DoesNotExist:
            # 邮箱不存在,返回错误提示
            return render(request, 'EmpLogin.html', {'msg': "邮箱或密码错误"})
        
        # 用用户存储的哈希密码验证输入的明文密码
        if check_password(user_password, user.user_password):
            # 验证通过,设置会话信息
            request.session['logged_in'] = True
            request.session['user_email'] = user.user_email
            request.session['u_id'] = user.user_email
            request.session['user_name'] = user.user_name
            request.session['u_type'] = "emp"
            return HttpResponseRedirect('/user_index')
        else:
            # 密码错误,返回提示
            return render(request, 'EmpLogin.html', {'msg': "邮箱或密码错误"})
    else:
        return render(request, 'EmpLogin.html')

关键修改说明

  • 用get()替代filter():因为邮箱是主键,确保返回单个用户对象,而非查询集合
  • 正确传递参数给check_password():第二个参数是用户对象的user_password属性(字符串类型的哈希值)
  • 增加异常捕获:处理邮箱不存在的情况,避免程序崩溃
  • 先验证密码再登录:只有密码验证通过后,才设置会话并跳转,修复了原逻辑的安全漏洞

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.29 11:57:35