简体   繁体   English

异常值:'QuerySet' 对象没有属性 'password'

[英]Exception Value: 'QuerySet' object has no attribute 'password'

I'm getting an error Query set object has no attribute 'password'.Can any one please help me how to compare user entered password with return <QuerySet [<Customer: Customer object (42)>]> query set.我收到一个错误查询集对象没有属性“密码”。任何人都可以帮助我如何比较用户输入的密码与返回<QuerySet [<Customer: Customer object (42)>]>查询集。 Please find the below views.py for login.请找到以下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(models):客户.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)

case b: When I am using get instead of filter.情况 b:当我使用 get 而不是 filter 时。

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})

Problem : It is not redirecting to home page i think there is some problem in this line (*flag = check_password(password, login_customer.password)* ).问题:它没有重定向到主页,我认为这一行存在一些问题(*flag = check_password(password, login_customer.password)* )。

Output in Terminal:终端输出:

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

#How encrypting password #如何加密密码

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)

Your login_customer variable is a queryset, not an instance of your Customer model.您的login_customer变量是一个查询集,而不是您的Customer模型的实例。 querysets are conceptually similar to a list , and in your case, it would be a list of customers .查询集在概念上类似于list ,在您的情况下,它将是一个customer 列表

You already have the fix for this in your second view;您已经在第二个视图中解决了这个问题; use Customer.objects.get instead.改用Customer.objects.get

The second issue is with your password management.第二个问题是您的密码管理。 if you take a look at the docs for check_password , you'll see that the second argument expects a password hash , and not 2 identical strings like in your case.如果您查看check_password的文档,您会发现第二个参数需要一个密码 hash ,而不是像您的情况一样的 2 个相同的字符串。

I'll spare you the lecture on why plain text passwords are bad .我不会给你讲为什么纯文本密码不好的讲座。 If you are interested, check out Information Security .如果您有兴趣,请查看Information Security

Anyways, you have 2 options:无论如何,您有两个选择:

( don't do this! ) Use the unsafe plain text passwords, and throw out the check_password function, in place of a simple if/else : 不要这样做! )使用不安全的纯文本密码,并丢弃check_password函数,代替简单的 if/else :

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

Use django's builtin LoginView .使用 django 的内置LoginView This will require some refactoring of your code, but this is a much better solution long term.这将需要对您的代码进行一些重构,但从长远来看,这是一个更好的解决方案。

models.py:模型.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:视图.py:

from django.contrib.auth import views

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

You will also need to change your template to use the login form object.您还需要更改模板以使用登录表单对象。 Here is the example from the 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>

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM