如何从Django QuerySet中获取指定属性值实现登录密码校验
Django登录功能数据库密码值提取方案
问题现象
开发网页登录功能做密码校验时,通过Django ORM查询得到的密码结果为QuerySet格式,打印输出为<QuerySet [{'password': 'password1234'}]>,无法直接获取字符串格式的密码值和用户输入密码做比对,原有代码如下:
def login(request): if request.method == "POST": form = LoginForm(request.POST) if form.is_valid(): email = form.cleaned_data.get("email") password_entered = form.cleaned_data.get("password") find_person_by_email = Person.objects.filter(email=email) password_from_DB = find_person_by_email.values("password") print(password_from_DB) if password_from_DB != password_entered : print("INCORRECT") else: print("CORRECT") context = {"title": "Login"} return render(request, "myApp/login.html", context)
问题原因
Person.objects.filter(email=email)返回的是所有匹配邮箱条件的记录集合(QuerySet),哪怕仅匹配到1条记录,返回值依然是集合类型,不是单个数据对象- 后续调用
.values("password")返回的结果依然是QuerySet类型,内部存储的是包含字段键值对的字典列表,直接和字符串类型的用户输入密码做比对,结果永远为不相等
实现方案
1. 推荐写法(适配邮箱唯一约束场景)
用户表的邮箱字段一般会设置唯一约束,直接用.get()替代.filter()获取单个用户对象,直接读取对象的password属性即可得到字符串结果:
def login(request): if request.method == "POST": form = LoginForm(request.POST) if form.is_valid(): email = form.cleaned_data.get("email") password_entered = form.cleaned_data.get("password") # 直接获取匹配邮箱的单个用户对象 user = Person.objects.get(email=email) password_from_DB = user.password print(password_from_DB) # 输出为字符串格式:password1234 if password_from_DB != password_entered : print("INCORRECT") else: print("CORRECT") context = {"title": "Login"} return render(request, "myApp/login.html", context)
2. 兼容原有filter+values逻辑的写法
如果保留原有filter查询逻辑,需要先从QuerySet中取出第一个结果字典,再读取字典内的password键值:
find_person_by_email = Person.objects.filter(email=email) # 取QuerySet第一个元素(字典),再读取password字段值 password_from_DB = find_person_by_email.values("password")[0]["password"]
安全提示
不建议在数据库中明文存储用户密码,存在严重的数据泄露风险。Django内置了密码哈希加密、校验能力,正式环境请使用内置的
check_password()方法做密码校验,不需要手动读取明文密码比对,参考写法:from django.contrib.auth.hashers import check_password user = Person.objects.get(email=email) # 直接传入用户输入的明文密码、数据库存储的哈希密码即可完成校验 if check_password(password_entered, user.password): print("CORRECT") else: print("INCORRECT")
内容的提问来源于stack exchange,提问作者logan_9997
相关产品推荐
相关产品推荐

