#python #django
#python #django
Вопрос:
В основном то, что я сделал до сих пор, — это создать страницу регистрации, где пользователь вводит свое имя пользователя и пароль, затем этот пароль сохраняется в виде хэшированного пароля (md5 hasher). Проблема, с которой я сталкиваюсь, заключается в входе в систему. Пользователь вводит свое имя пользователя и пароль, затем пароль аутентифицируется с помощью метода authenticate() в django. Проблема в том, что authenticate() возвращает None вместо сопоставления пользователя и пароля в базе данных. Я не знаю, влияет ли это на что-либо, но я использую PostgreSQL.
models.py
class MyAccountManager(BaseUserManager):
def create_user(self, email,username,first_name,password= None):
if not email:
raise ValueError('User must have an email address')
if not username:
raise ValueError('User must have a username')
if not first_name:
raise ValueError('User must have a first name')
user= self.model(
email=self.normalize_email(email),
username= username,
first_name= first_name
)
user.set_password(password)
user.save(using=self._db)
return user
def create_superuser(self, email, username, first_name, password):
user= self.create_user(
email= self.normalize_email(email),
username=username,
first_name= first_name,
password= password,
)
user.is_admin= True
user.is_staff= True
user.is_superuser= True
user.save(using=self._db)
return user
class User(AbstractBaseUser, models.Model):
email = models.EmailField(verbose_name='email', max_length=60, unique=True)
username = models.CharField(max_length=30, unique=True)
date_joined = models.DateTimeField(auto_now_add=True, verbose_name='date joined')
last_login = models.DateTimeField(verbose_name='last login', auto_now=True)
is_admin = models.BooleanField(default=False)
is_staff = models.BooleanField(default=False)
is_superuser = models.BooleanField(default=False)
is_active = models.BooleanField(default=True)
first_name = models.CharField(max_length=30)
last_name = models.CharField(max_length=30)
USERNAME_FIELD= 'username'
REQUIRED_FIELDS= ['email','first_name']
objects= MyAccountManager()
def __str__(self):
return self.email
def has_perm(self, perm, obj=None):
return self.is_admin
def has_module_perms(self, app_label):
return True
forms.py
class LoginForm(forms.Form):
username = forms.CharField(initial='' ,label='Username:',max_length=30)
password = forms.CharField(max_length=20, widget=forms.PasswordInput())
class Meta:
model = User
fields = ('username', 'password')
def clean(self):
cleaned_data = super(LoginForm, self).clean()
confirm_password = cleaned_data.get('password')
class SignUpForm(forms.ModelForm):
first_name = forms.CharField(required= True,initial='',max_length=20)
last_name = forms.CharField(required=True,max_length=30, initial='')
username = forms.CharField(max_length=30,initial='', required=True)
password = forms.CharField(max_length= 20, initial='', widget = forms.PasswordInput())
password2= forms.CharField(max_length=20, initial='',widget = forms.PasswordInput())
email = forms.EmailField(max_length=60, initial='',)
class Meta:
model = User
fields = ('first_name', 'last_name','username','password2','email')
def clean(self):
cleaned_data = super(SignUpForm,self).clean()
password = cleaned_data.get('password')
confirm_password = cleaned_data.get('password2')
if(password != confirm_password):
raise forms.ValidationError(
'Password and Confirm Password do not match.'
)
views.py
def signin_and_signup(request):
if request.method == 'POST':
logout(request)
sign_in = LoginForm(request.POST)
signup = SignUpForm(request.POST)
if 'sign-in-name' in request.POST:
if sign_in.is_valid():
username = request.POST.get('username')
password= request.POST.get('password')
user = authenticate(username= username, password= password)
if user:
return HttpResponse('success')
else:
return HttpResponse('fail')
elif 'sign-up-input-name' in request.POST:
if(signup.is_valid()):
user = signup.save(commit=False)
nonHashed = signup.cleaned_data['password']
varhash = make_password(nonHashed, None, 'md5')
user.set_password(varhash)
user.save()
else:
print("Ran3<------------")
signup = SignUpForm()
else:
sign_in = LoginForm()
signup = SignUpForm()
context = {'signin':sign_in, 'signup':signup}
return render(request, 'home.html', context)
Ответ №1:
Почему вы заменяете модель пользователя, которую предоставляет django, если у вас те же атрибуты? Это делается на случай, если вы хотите расширить или добавить новые свойства для пользователя, например, номер лицензии, аватар, должность.
В любом случае, ваш authenticate(), возможно, не работает, потому что вы не зарегистрировали свою новую модель в settings.py .
AUTH_USER_MODEL = 'name_of_the_app.User'
Я рекомендую вам взглянуть на официальную документацию
https://docs.djangoproject.com/en/3.1/topics/auth/customizing /
Другое дело, что это может быть ваш сервер аутентификации:
Попробуйте:
settings.py
AUTHENTICATION_BACKENDS = [
'name_of_the_app.admin.LoginBackend',
]
Где вы хотите, например admin.py
from django.contrib.auth.backends import ModelBackend, UserModel
from django.db.models import Q
class LoginBackend(ModelBackend):
def authenticate(self, request, username=None, password=None, **kwargs):
try: # to allow authentication through phone number or any other field, modify the below statement
user = UserModel.objects.get(Q(username__iexact=username) | Q(email__iexact=username))
except UserModel.DoesNotExist:
UserModel().set_password(password)
except MultipleObjectsReturned:
return models.User.objects.filter(email=username).order_by('id').first()
else:
if user.check_password(password) and self.user_can_authenticate(user):
return user
def get_user(self, user_id):
try:
user = UserModel.objects.get(pk=user_id)
except UserModel.DoesNotExist:
return None
return user if self.user_can_authenticate(user) else None
Как вы можете видеть, вы также можете войти в систему с помощью электронной почты
Комментарии:
1. У меня уже есть AUTH_USER_MODEL в моем settings.py вот почему я действительно в замешательстве
2. @kixsmart Теперь проверьте серверную часть аутентификации:
3. да, чувак, в чем проблема, ничего не работает. Idk, если это имеет значение, но пароль хэшируется с помощью md5