我想为用户制作一个注册/登录API。 问题是这样的: 如果我通过管理站点创建用户,登录可以正常工作。
如果我通过我制作的注册页面创建用户,登录将无法正常工作。(authenticate() 函数返回 None,即使该用户仍在用户表中。)
我转到管理站点,转到更改密码的链接并再次提供相同的密码。之后我就可以成功登录了。
我认为问题在于保存密码或登录。 我已经交叉检查了很多,但无法弄清楚。 我正在提供所有文件。您可能会浏览重要的代码。
模型.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
表单.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')
View .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)
注册.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>
最佳答案
问题在于您如何设置密码。您已从模型表单的字段列表中排除了密码,因此在保存时不会设置密码。因此,执行 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 是不必要的;现在更是如此,所以你应该删除它。
关于python - Django : authenticate() is not working for users created by register page, 但适用于由管理员创建的用户,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39164249/