【问题标题】:Exception Value: 'QuerySet' object has no attribute 'password'异常值:“QuerySet”对象没有属性“密码”
【发布时间】:2020-10-17 03:21:17
【问题描述】:

我收到一个错误查询集对象没有属性“密码”。谁能帮助我如何比较用户输入的密码和返回 ]> 查询集。 请在下面找到 views.py 进行登录。

def login(request):
    if request.method == 'GET':
        return render (request, 'login.html')

    else:
        email = request.POST.get('email')
        password = request.POST.get('password')
        print(email,password)
        #Now we will try to match user entered email ID and search it in db(here we Can't use pass because it is in ecrypted mode we can see from admin panel
        # to filter result we can use Customer.objects.filter which will return match in list form but we want a single object so better is to use get
        # Customer.objects.get(email=email))
        #drawback of get is that if result is matched then good else it will give error.

        login_customer = Customer.objects.filter(email=email)
        print(login_customer)
        print('-------')
        error = None
        if login_customer:
            print(email)
            flag = check_password(password, login_customer.password)
            #if user email ID is exit then we'll Check his password.:)
            if flag:
                return redirect('home')
        else:
            print(email, password)
            error = 'Entered Email ID OR Password is incorrect'

        return render(request, 'login.html',{'error':error})

customer.py(模型):

from django.db import models
##Customer Model Creation.

# Create your models here.

class Customer(models.Model):
    first_name = models.CharField(max_length=50)
    last_name = models.CharField(max_length=50)
    phone = models.CharField(max_length=15)
    email = models.EmailField()
    password = models.CharField(max_length=250)

案例 b:当我使用 get 而不是过滤器时。

def login(request):
    if request.method == 'GET':
        return render (request, 'login.html')

    else:
        email = request.POST.get('email')
        password = request.POST.get('password')
        print(email,password)
        #Now we will try to match user entered email ID and search it in db(here we Can't use pass because it is in ecrypted mode we can see from admin panel
        # to filter result we can use Customer.objects.filter which will return match in list form but we want a single object so better is to use
        # Customer.objects.get(email=email))
        #drawback of get is that if result is matched then good else it will give error.so better is to use
        login_customer = Customer.objects.get(email=email)
        print(login_customer)
        print('-------')
        error = None
        if login_customer:
            print(email)
            print('+++++')
            flag = check_password(password, login_customer.password)
            #if user email ID is exit then we'll Check his password.:)
            if flag:
                return redirect('home')
        else:
            print(email, password)
            error = 'Entered Email ID OR Password is incorrect'

        return render(request, 'login.html',{'error':error})

问题:它没有重定向到主页我认为这行有问题(*flag = check_password(password, login_customer.password)*)。

终端输出:

Django version 3.0.2, using settings 'ShaileshShop.settings'
Starting development server at http://127.0.0.1:8000/
Quit the server with CONTROL-C.
sheru@apple.com None
Customer object (42)
-------
sheru@apple.com
+++++
[17/Oct/2020 03:14:26] "POST /login HTTP/1.1" 200 5167

#如何加密密码

from django.contrib.auth.hashers import make_password,check_password
    def signup(request):
        if request.method == 'GET':
                print(request.method)
                return render(request,'signup.html')
        else:
            postdata=request.POST
            first_name = postdata.get('firstname')
            last_name = postdata.get('lastname')
            phone = postdata.get('PhoneNumber')
            email = postdata.get('email')
            password = postdata.get('Password')
    
            #Now to store filled data if any error is coming so that User not required to fill it again.####
            value={
                'first_name' : first_name,
                'last_name' : last_name,
                'phone' : phone,
                'email' : email,
                #password not passing :) user need to fill it hahhahaa
            }
            
    
            ####Validating above field at server level####
            error = None
            customer = Customer(first_name=first_name,
                                last_name=last_name,
                                phone=phone,
                                email=email,
                                password=password)
            if not first_name:
                error = 'First name is required!!'
            elif len(first_name) < 4:
                error = 'First Name must be 4 char length'
    
            elif not last_name:
                error ='Last Name is required!.'
            elif len(last_name) < 4:
                error = 'Last Name Must be 4 Character long.'
    
            elif len(phone) < 10:
                error ='Mobile number should be of 10 digit.'
            
            elif Customer.objects.filter(phone=phone):
                error = "Mobile no is already registered."
    
            elif len(password) < 5:
                error ="Password must be 5 Char length."
            
            elif len(email) <6:
                error = "Email Id must be more than 6 Character !"
    
            elif Customer.objects.filter(email=email):
                error = "Sorry You already have account with this Email ID."
    
    
            if not error:
                print(first_name,last_name,email,password,phone)
                customer.password = make_password(customer.password)
    
                customer.save()
                #best way is to go into urls.py and define name=hompage because tommorow if we'll upload on production this domain will change.
                return redirect('home')
                # return redirect('http://127.0.0.1:8000')this is not recommonded
                # return render(request,'index.html')#paasing data otherwise product will not shown to us after redirecting to index.
                # in this we will not get all product image so we need to check how we can use above data already written code
    
            else:
                data = {
                    'error': error,
                    'values': value,
                }
                return render(request,'signup.html', data)

【问题讨论】:

  • 在您的登录视图中,print(login_customer.password) 的结果是什么?
  • 它以加密形式给我密码 print(login_customer.password) pbkdf2_sha256$180000$BUsJchRCQdo0$S4WD7GNZNMhAT9a7UBu5FX0qra8rHpuZXYG3q+/nniw=(在数据库中签入也同样通过。)------------ -------------------------------------------------- --------------- x=make_password(password) print(x) o/p:!Ba41NTEVRFHUpyPu43MHy7ss58a4esWChbIWEp8l

标签: python django django-views


【解决方案1】:

您的 login_customer 变量是一个查询集,不是您的 Customer 模型的实例。查询集在概念上类似于 列表,在您的情况下,它是一个客户列表

您已经在第二个视图中对此进行了修复;请改用Customer.objects.get

第二个问题是您的密码管理。如果您查看 check_password 的文档,您会发现第二个参数需要一个 密码哈希,而不是像您的情况那样的 2 个相同的字符串。

关于为什么纯文本密码不好,我就不给你讲课了。如果您有兴趣,请查看 Information Security

无论如何,你有两个选择:

不要这样做!) 使用不安全的纯文本密码,并丢弃 check_password 函数,代替简单的 if/else :

if password == login_customer.password:
    return redirect('home')
else:
    ...

使用 django 的内置 LoginView。这将需要对您的代码进行一些重构,但从长远来看,这是一个更好的解决方案。

models.py:

from django.contrib.auth.models import AbstractUser

# all other fields are already included in `AbstractUser`
class Customer(AbstractUser):
    USERNAME_FIELD = "email"

    email = models.EmailField(unique=True, db_index=True)

views.py:

from django.contrib.auth import views

class LoginView(views.LoginView):
    template_name = 'login.html'

您还需要更改模板以使用登录表单对象。以下是来自docs 的示例:

<form method="post" action="{% url 'login' %}">
{% csrf_token %}
<table>
<tr>
    <td>{{ form.username.label_tag }}</td>
    <td>{{ form.username }}</td>
</tr>
<tr>
    <td>{{ form.password.label_tag }}</td>
    <td>{{ form.password }}</td>
</tr>
</table>

<input type="submit" value="login">
<input type="hidden" name="next" value="{{ next }}">
</form>

【讨论】:

  • 谢谢! @ Elrond 支持 Monica,在 check_password(password, login_customer.password) 中,第二个参数仅加密来自 db。如果我使用 if password == login_customer.password: return redirect('home') here 我会得到 Password not match 因为 login_customer.password 是更简洁的文本形式,而密码是用户输入的(纯文本)。
  • @ShaileshYadav 你能展示你是如何创建密码哈希的吗?我猜您使用的方法与check_password 所期望的方法不同。
  • @ Elrond 支持我使用的 Monica from django.contrib.auth.hasher import make_password,check_password 例如 print(make_password('1234')) print(check_password('1234','pbkdf2_sha256$180000 $gj9Y5muPZKgx$YdcCE+Wvz0AIBwXSa4yNW0piDPJzfJVx46K4uqBCc1c=')) 在这里我复制了加密代码,第二次打印我们将得到 True。同时更新注册视图请检查。
  • 它在没有做任何更改的情况下工作,我在 Firefox 浏览器中尝试过,发现它正在工作,后来在 safari 中也能正常工作。(这是浏览器特定的问题,输入密码是 Showing None 所以比较在 None=password 之间发生存储在数据库中)。谢谢!
猜你喜欢
  • 2020-08-25
  • 1970-01-01
  • 2020-10-31
  • 1970-01-01
  • 2021-06-12
  • 2021-06-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多