Django:authenticate()不适用于由注册页面创建的用户,但适用于由admin创建的用户

时间:2016-08-26 10:35:23

标签: python django django-views

我想为用户制作注册/登录API。 问题是这样的: 如果我通过管理站点创建用户,则登录正常。

如果我通过我创建的注册页面创建用户,则登录不工作。(authenticate()函数返回None,即使该用户仍在用户表中。)

我转到管理站点,转到更改密码的链接并再次输入相同的密码。之后我可以成功登录。

我认为问题在于保存密码或登录。 我已经检查了很多,但无法弄清楚。 我正在提供所有文件。您可以浏览重要的代码。

models.py     

from __future__ import unicode_literals
from django.db import models
from django.contrib.auth.models import User
from datetime import datetime

class Recruiter(models.Model):
    user = models.OneToOneField(User, on_delete=models.CASCADE)
    company_name = models.CharField(max_length=120)
    HR_office_number = models.CharField(max_length=15)
    HR_mobile_number = models.CharField(max_length=15)

def __str__(self):
    return self.user.username

forms.py     

from django import forms
from .models import Recruiter, User
from django.core.exceptions import ValidationError

class UserForm(forms.ModelForm):
    password = forms.CharField(widget=forms.PasswordInput(), max_length=128)
    confirm_password = forms.CharField(widget=forms.PasswordInput(), max_length=128)
    class Meta:
        model = User
        fields = ['first_name', 'last_name', 'username', 'email']

    def __init__(self, *args, **kwargs):
        super(UserForm, self).__init__(*args, **kwargs)
        self.fields['first_name'].required = True
        self.fields['last_name'].required = True
        self.fields['email'].required = True
        self.fields['username'].help_text = None

    def clean_confirm_password(self):
        password1 = self.cleaned_data.get('password')
        password2 = self.cleaned_data.get('confirm_password')
        if not (password1 and password2):
            raise forms.ValidationError("You must confirm your password")
        elif password1 != password2:
            raise forms.ValidationError("Your passwords do not match")
        return password1


class RecruiterForm(forms.ModelForm):
    class Meta:
        model = Recruiter
        fields = ('company_name', 'HR_mobile_number', 'HR_office_number')

views.py     

from django.shortcuts import render
from django.contrib.auth.models import User
from .models import Recruiter
from .forms import RecruiterForm, UserForm, RecruiterLoginForm
from django.urls import reverse
from django.http import HttpResponse,HttpResponseRedirect
from django.db import IntegrityError
from django.contrib.auth import authenticate, login, logout

def register(request):
    context = request.POST
    registered = False

    if request.method == 'POST':
        user_form = UserForm(data=request.POST)
        recruiter_form = RecruiterForm(data=request.POST)
        if user_form.is_valid() and recruiter_form.is_valid():
            user = user_form.save()
            try:
                user.set_password(user.password)
                user.save()
            except IntegrityError as e:
                user.delete()
                return HttpResponse(e.message)
            try:
                recruiter = recruiter_form.save(commit=False)
                recruiter.user = user
                recruiter.save()
            except IntegrityError as e:
                recruiter.delete()
                return HttpResponse(e.message)
            registered = True
        else:
            pass
            #print form.errors
    else:
        recruiter_form = RecruiterForm()
        user_form = UserForm()

    return render(request, 'recruiter/register.html', {'user_form':user_form,
                'recruiter_form':recruiter_form, 'registered':registered}, context)



def login_recruiter(request):
    context = request.POST
    if request.user.is_authenticated():
        return HttpResponse("Logged in")
    if request.method == 'POST':
        username = request.POST['username']
        password = request.POST['password']
        user = authenticate(username=username, password=password)
        print user
        if user:
            if user.is_active:
                login(request, user)
                return HttpResponse("Success")
            else:
                return HttpResponse("Not active")
        else:
            return HttpResponse("Invalid")
    else:
        return render(request, 'recruiter/login_recruiter.html', {}, context)

register.html     

{% if registered %}
    <h1>Registered</h1><br />
{% else %}
<form id="user_form" method="post" action="{% url 'recruiter:register' %}" enctype="multipart/form-data">
    {% csrf_token %}
    {{ user_form.as_p}}
    {{ recruiter_form.as_p}}
    <input type="submit" name="submit" value="Register" />
</form>
{% endif %}

login_recruiter.html     

<form id="login_form" method="post" action="{% url 'recruiter:login_recruiter' %}">
        {% csrf_token %}
        Username: <input type="text" name="username" value="" size="120" />
        <br />
        Password: <input type="password" name="password" value="" size="120" />
        <br />
        <input type="submit" value="submit" />
</form>

2 个答案:

答案 0 :(得分:2)

问题在于您如何设置密码。您已从模型表单上的字段列表中排除了密码,因此未在保存时设置。因此,user.set_password(user.password)有效地将密码设置为None的散列。相反,这样做:

user = user_form.save(commit=False)
user.set_password(user_form.cleaned_data['password']
user.save()

请注意,即使在您的原始代码中,也无法设置密码可能导致IntegrityError,因此不需要try / except;现在更是如此,所以你应该删除它。

答案 1 :(得分:0)

使用以下代码解决它..

def register(request, template_name="registration/register.html"):
    if request.method == "POST":
        postdata = request.POST.copy()
        username = postdata.get('username', '')
        email = postdata.get('email', '')
        password = postdata.get('password', '')

        # check if user does not exist
        if User.objects.filter(username=username).exists():
            username_unique_error = True

        if User.objects.filter(email=email).exists():
            email_unique_error = True

        else :
            create_new_user = User.objects.create_user(username, email, password)
            create_new_user.save()
            user = authenticate(username=username, password=password)
            login(request, user)
            if create_new_user is not None:
                if create_new_user.is_active:
                    return HttpResponseRedirect('/profile')
                else:
                    print("The password is valid, but the account has been disabled!")


    return  render(request, template_name, locals())


def log_in(request, template_name="registration/login.html"):
    page_title = "Login"
    if request.method == "POST":
        postdata = request.POST.copy()
        username = postdata.get('username', '')
        password = postdata.get('password', '')

        try:
            user = authenticate(username=username, password=password)
            login(request, user)

            return HttpResponseRedirect('/profile')
        except :
            error = True

    return render(request, template_name, locals())
相关问题