Как я могу войти в свою пользовательскую модель пользователя? AuthenticationForm или моя собственная пользовательская форма входа не будут проверяться

Я создал пользовательскую модель пользователя, создав подкласс AbstractUser.

У меня есть представление регистрации, шаблон и CustomUserCreationForm, которые, кажется, работают нормально и могут без проблем регистрировать пользователей через внешний интерфейс.

Моя проблема заключается в том, что пользователь вошел в систему. Кажется, я не могу пройти проверку формы для их аутентификации. Я всегда возвращаюсь с пользовательским объектом None

Например, с этой строкой я всегда получаю None, эта ошибка проверки

            user = authenticate(request, email=email, password=password)
            # user = User.objects.get(email=email, password=hashed_pass)

            # Check if authentication successful
            if user is not None:
                login(request, user)
                return HttpResponseRedirect(reverse("clientcare:portal/dashboard"))
            else:
                return render(request, "clientcare/login.html", {
                    "message": "Invalid email and/or password.",
                    'login_form':LoginForm,
                })

Формы

class CustomUserCreationForm(UserCreationForm):

    class Meta(UserCreationForm.Meta):
        model = User
        fields = ('email', 'first_name','last_name' ,'city', 'province','age','gender','phone_number','password1', 'password2',)

class LoginForm(forms.Form):
    email = forms.EmailField(max_length=100)
    password = forms.CharField(widget = forms.PasswordInput())

class CustomUserChangeForm(UserChangeForm):

    class Meta:
        model = User
        fields = ('email', 'first_name','last_name' ,'city', 'province','age','gender','phone_number',)


Модели

# Create your models here.
class UserManager(BaseUserManager):
    use_in_migrations = True

    def _create_user(self, email, password, **extra_fields):
        if not email:
            raise ValueError('Users require an email field')
        email = self.normalize_email(email)
        user = self.model(email=email, **extra_fields)
        user.set_password(password)
        user.save(using=self._db)
        return user

    def create_user(self, email, password=None, **extra_fields):
        extra_fields.setdefault('is_staff', False)
        extra_fields.setdefault('is_superuser', False)
        extra_fields.setdefault('is_patient', False)
        extra_fields.setdefault('is_provider', True)
        return self._create_user(email, password, **extra_fields)

    def create_superuser(self, email, password, **extra_fields):
        extra_fields.setdefault('is_staff', True)
        extra_fields.setdefault('is_superuser', True)

        if extra_fields.get('is_staff') is not True:
            raise ValueError('Superuser must have is_staff=True.')
        if extra_fields.get('is_superuser') is not True:
            raise ValueError('Superuser must have is_superuser=True.')

        return self._create_user(email, password, **extra_fields)


class User(AbstractUser):
    username = None
    email = models.EmailField(_('email address'), unique=True)
    image_height = models.PositiveIntegerField(null=True, blank=True, editable=False, default = "200")
    image_width = models.PositiveIntegerField(null=True, blank=True, editable=False, default = "200")
    date_joined = models.DateTimeField(auto_now=True, null=False, blank=False)
    city = models.CharField(null=False, blank=False, max_length=20)
    province = models.CharField(null=False, blank=False, max_length=20)
    profile_image_url = models.ImageField(null=True, blank=True, upload_to='images/', editable=True)    
    paid = models.BooleanField(default=False)
    phone_number = PhoneField(blank=True, null=True, help_text='Contact phone number', E164_only=False)
    in_trial = models.BooleanField(default=True)
    recently_active = models.BooleanField(default=True)
    gender = models.CharField(choices=(("Male", "Male"),("Female", "Female"), ("Other", "Other")), max_length=6, default = "Male", null=False, blank=False)
    age = models.SmallIntegerField(max_length=3,null=False, blank=False)
    objects = UserManager()

    USERNAME_FIELD = 'email'
    REQUIRED_FIELDS = ['first_name', 'last_name',]
    # classify if the user is a provider or a patient
    is_patient = models.BooleanField('Patient status',default=False)
    is_provider = models.BooleanField('Provider status',default=False)

    def __str__(self):
        return f"{self.get_full_name()}"

Вход в систему

def login_view(request):

    if request.method == "POST":

        login_form = LoginForm(data=request.POST)
        if login_form.is_valid():
            email = login_form.cleaned_data['email']
            password = login_form.cleaned_data['password']

            # hashed_pass = bcrypt.hashpw(raw_pass, salt)
            # if bcrypt.checkpw(raw_pass, hashed_pass):
            user = authenticate(request, email=email, password=password)
            # user = User.objects.get(email=email, password=hashed_pass)

            # Check if authentication successful
            if user is not None:
                login(request, user)
                return HttpResponseRedirect(reverse("clientcare:portal/dashboard"))
            else:
                return render(request, "clientcare/login.html", {
                    "message": "Invalid email and/or password.",
                    'login_form':LoginForm,
                })
        else:
            return render(request, "clientcare/login.html", {
                "message": "Invalid login data. Please try again",
                'login_form':LoginForm,
            })
    else:
        return render(request, "clientcare/login.html", {
            'login_form':LoginForm,
        })

Просмотр регистрации

def register(request):

    # Adding the salt to password

    if request.method == "POST":

        register_form = CustomUserCreationForm(request.POST)
        if register_form.is_valid():
            email = register_form.cleaned_data['email']
            city = register_form.cleaned_data["city"]
            province = register_form.cleaned_data["province"]
            first_name = register_form.cleaned_data["first_name"]
            last_name = register_form.cleaned_data["last_name"]
            phone_number = register_form.cleaned_data["phone_number"]
            age = register_form.cleaned_data["age"]
            gender = register_form.cleaned_data["gender"]

            # Ensure password matches confirmation
            password = register_form.cleaned_data["password1"]
            confirmation = register_form.cleaned_data["password2"]
            if password != confirmation:
                return render(request, "clientcare/register.html", {
                    "messsage": "Passwords must match."
                })

            # Hashing the password
            # hashed = bcrypt.hashpw(password, salt)
            # password = hashed

            # Attempt to create new user
            try:
                user = User.objects.create(email=email, city=city, province=province, password=password, first_name=first_name, last_name=last_name, phone_number=phone_number, age=age, gender=gender)
                user.save()
            except IntegrityError:
                return render(request, "clientcare/register.html", {
                    "message": "ERROR. TRY AGAIN",
                })
            login(request, user)
            return HttpResponseRedirect(reverse("clientcare:index"))
        else:
            return render(request, "clientcare/register.html", {
                "message": "ERROR. PLEASE CONFIRM REGISTRATION INFO",
            })
    else:
        return render(request, "clientcare/register.html",{
            'registration_form':CustomUserCreationForm
        })

У меня есть мой пользователь в settings.py как таковой:

AUTH_USER_MODEL = 'clientcare.User'

Я хорошо знаю, что могу использовать AllAuth или другие библиотеки аутентификации. Но я пытаюсь понять вещи на более низком уровне, прежде чем использовать такие библиотеки. Любая помощь будет оценена по достоинству.

Ничто из того, что я пытаюсь сделать, не работает для входа в мою пользовательскую модель пользователя. Нужно ли мне писать собственный бэкэнд? AuthenticationForm, похоже, не работает, так как моя собственная форма входа не проверяется

ОДНАКО, если я обновлю пароль пользователя через администратора (с суперпользователем), то пользователь сможет без проблем войти в систему с обновленным паролем ... поэтому моя CustomUserChangeForm выполняет эту работу. Что мне не хватает?

Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
0
0
54
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Я помещаю здесь модель моего старого проекта в качестве примера. Здесь я использовал пользовательскую модель как есть и добавил поля, которые хотел добавить в новый класс, где пользователь также является полем. Модуль аутентификации Django работает как есть, и никакого дополнительного кода не требуется.

from django.contrib.auth.models import User
from django.db import models
from django.utils.translation import ugettext_lazy as _
from backend.custom_fields import AutoOneToOneField
from backend import definitions
from django.urls import reverse
from django.db.models.signals import post_save
from django.dispatch import receiver
from backend.convert import convert_string_to_url_safe
from random import randint
from backend.image_operation import image_resize, image_convert_to_jpg


EMAIL_PRIVACY_CHOICES = (
    (0, _('Display your e-mail address.')),
    (1, _('Hide your e-mail address but allow form e-mail.')),
    (2, _('Hide your e-mail address and disallow form e-mail.')),
)

PHONE_PRIVACY_CHOICES = (
    (0, _('Display your phone no.')),
    (1, _('Hide your phone no.')),
)


def avatar_upload_file_name_path(instance, filename_ext):
    ext = filename_ext.split('.')[-1]
    return f'profile_uploads/{convert_string_to_url_safe(instance.get_full_name)}-{randint(1000, 10000)}.{ext}'


def photo_upload_file_name_path(instance, filename_ext):
    ext = filename_ext.split('.')[-1]
    return f'profile_uploads/{convert_string_to_url_safe(instance.get_full_name)}-{randint(1000, 10000)}.{ext}'


def resized_photo_upload_file_name_path(instance, filename_ext):
    ext = filename_ext.split('.')[-1]
    return f'profile_uploads/resized-{convert_string_to_url_safe(instance.get_full_name)}-{randint(1000, 10000)}.{ext}'


class PlatformUser(models.Model):
    user = AutoOneToOneField(User, on_delete=models.CASCADE)
    slug = models.CharField(max_length=100, null=True, blank=True)
    title = models.CharField(max_length=60, blank=True, default='')
    description = models.TextField(blank=True, default='')
    phone = models.CharField(max_length=25, blank=True, default='')
    facebook_address = models.URLField(blank=True, default='')
    twitter_address = models.URLField(blank=True, default='')
    instagram_address = models.URLField(blank=True, default='')
    linkedin_address = models.URLField(blank=True, default='')
    youtube_address = models.URLField(blank=True, default='')
    site = models.URLField(_('Personal Site'), blank=True)
    skype_name = models.CharField(_('Skype Name'), max_length=100, blank=True, default='')
    birth_date = models.DateTimeField(_('Birth Date'), blank=True, null=True)
    location = models.CharField(_('Location'), max_length=30, blank=True)
    photo = models.ImageField(upload_to=photo_upload_file_name_path, blank=True, default='')
    photo_resized = models.ImageField(upload_to=resized_photo_upload_file_name_path, blank=True, null=True)
    show_photo = models.BooleanField(_('Show avatar'), blank=True, default=True)
    show_signatures = models.BooleanField(_('Show signatures'), blank=True, default=True)
    show_smilies = models.BooleanField(_('Show smilies'), blank=True, default=True)
    email_privacy_permission = models.IntegerField(_('Privacy permission'), choices=EMAIL_PRIVACY_CHOICES, default=1)
    phone_privacy_permission = models.IntegerField(_('Privacy permission'), choices=PHONE_PRIVACY_CHOICES, default=1)
    auto_subscribe = models.BooleanField(_('Auto subscribe'),
                                         help_text=_("Auto subscribe all topics you have created or reply."),
                                         blank=True, default=False)
    post_count = models.IntegerField(_('Post count'), blank=True, default=0)
    likes_count = models.IntegerField(default=0)
    view_count = models.IntegerField(default=0)
    signature = models.TextField(_('Sign'), blank=True, default='', max_length=definitions.SIGNATURE_MAX_LENGTH)
    signature_html = models.TextField(_('Sign as HTML'), blank=True, default='',
                                      max_length=definitions.SIGNATURE_MAX_LENGTH)
    verification_code = models.CharField(_('Verify Code'), blank=True, default='', max_length=40)
    created = models.DateTimeField(_('Created'), auto_now_add=True)
    updated = models.DateTimeField(_('Updated'), auto_now=True, null=True)

    class Meta:
        ordering = ['user']
        get_latest_by = 'created'
        verbose_name = _('Platform Member')
        verbose_name_plural = _('Platform Members')

    def __init__(self, *args, **kwargs):
        super(PlatformUser, self).__init__(*args, **kwargs)
        self.__original_image_filename = self.photo.name

    @property
    def email(self):
        return self.user.email

    @property
    def get_full_name(self):
        full_name = str(self.user.first_name.title())
        if len(full_name) > 0:
            full_name += " "
        full_name += str(self.user.last_name.title())
        if len(full_name) == 0:
            full_name = self.user.username
        return full_name

    @property
    def username(self):
        return self.user.username

    @property
    def first_name(self):
        return self.user.first_name

    @property
    def last_name(self):
        return self.user.last_name

    def __str__(self):
        return f"[{self.user.first_name} {self.user.last_name}] - ({self.user.email})"

    def get_absolute_url(self):
        return reverse('profile',
                       args=[str(self.get_slug())])

    def get_slug(self):
        if not self.slug:
            self.slug = self.user.username
        return self.slug

    def save(self, *args, **kwargs):
        if not self.slug:
            self.slug = self.get_slug()

        if self.photo and (self.photo.name != self.__original_image_filename or not self.photo_resized):
            self.photo_resized = image_resize(400, 400, self.photo)
            self.photo = image_convert_to_jpg(self.photo)

        super(PlatformUser, self).save(*args, **kwargs)


@receiver(post_save, sender=User)
def create_user_profile(sender, instance, created, **kwargs):
    if created:
        PlatformUser.objects.create(user=instance)


@receiver(post_save, sender=User)
def save_user_profile(sender, instance, **kwargs):
    platform_users = PlatformUser.objects.filter(user=instance)

    if len(platform_users) > 0:
        platform_user = platform_users[0]
    else:
        platform_user = PlatformUser.objects.create(user=instance)

    platform_user.save()

как вы могли видеть, есть приемники для создания моей собственной строки пользователя платформы в базе данных при создании пользователя.

Этот способ простой, но полезный, на мой взгляд. Ваш способ более правильный, но более сложный.

Кстати, я не использую и вообще не люблю формы django.

Почему вам не нравятся формы джанго? И делать это так, как я пытаюсь, - это то, как я видел это в основном при поиске в Интернете.. хотя я определенно вижу прямолинейность вашей реализации.

s-knocks 27.12.2022 20:53

@s-knocks Потому что это очень сложно вписать в дизайн. Также есть проблема с кодами javascript.

Ferhat Mousavi 27.12.2022 20:59
Ответ принят как подходящий

Решено. Я понял, что не использовал метод create_user, который написал в своем представлении регистрации.

Обновлена ​​строка ниже:

user = User.objects.create_user(email=email, city=city, province=province, password=password, first_name=first_name, last_name=last_name, phone_number=phone_number, age=age, gender=gender)

После этого моя форма входа и проверка заработали. Поэтому для тех, у кого есть аналогичная проблема, убедитесь, что вы используете метод create_user, если вы его написали/если вы используете пользовательскую модель пользователя/если вы вызываете user.set_password(password) в этом методе, а не в вашем представлении.

Завтра первым делом займусь, когда мне разрешат :) спасибо!

s-knocks 28.12.2022 13:01

Другие вопросы по теме