Поле пароля в форме регистрации/логина не отображается должным образом | Django | HTML | Bootstrap

Я пытаюсь создать пользовательскую форму регистрации, используя HTML, CSS, Bootstrap как front end и Django как backend, когда я создаю форму, firstname, lastname и email отображаются как обязательные, но поля password и confirm_password не отображаются как обязательные, из forms.py, placeholder виджета и class=form-control также не применяются к нему.

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

  1. models.py
from django.contrib.auth.models import AbstractBaseUser, BaseUserManager
from django.db import models

class CustomUserManager(BaseUserManager):
    def create_user(self, email, first_name, last_name=None, password=None, **extra_fields):
        if not email:
            raise ValueError('The Email field must be set.')
        if not first_name:
            raise ValueError('The First Name field must be set.')
        if not password:
            raise ValueError('Password cannot be left blank.')
        
        email = self.normalize_email(email)
        user = self.model(email=email, first_name=first_name, last_name=last_name, **extra_fields)
        user.set_password(password)
        user.save(using=self._db)
        return user

class CustomUser(AbstractBaseUser):
    email = models.EmailField(unique=True)
    first_name = models.CharField(max_length=50)
    last_name = models.CharField(max_length=50, blank=True, null=True)
    is_active = models.BooleanField(default=True)
    is_staff = models.BooleanField(default=False)

    objects = CustomUserManager()

    USERNAME_FIELD = 'email'
    REQUIRED_FIELDS = ['first_name']

    def __str__(self):
        return self.email
  1. forms.py
from django import forms
from django.contrib.auth.forms import UserCreationForm
from .models import CustomUser

class SignUpForm(UserCreationForm):

    class Meta:
        model = CustomUser
        fields = ['first_name', 'last_name', 'email', 'password1', 'password2']
        widgets = {
            'first_name': forms.TextInput(attrs={'class': 'form-control', 'placeholder': 'Enter your first name'}),
            'last_name': forms.TextInput(attrs={'class': 'form-control', 'placeholder': 'Enter your last name'}),
            'email': forms.EmailInput(attrs={'class': 'form-control', 'placeholder': 'Enter your email'}),
            'password1': forms.PasswordInput(attrs={'class': 'form-control', 'placeholder': 'Enter password'}),
            'password2': forms.PasswordInput(attrs={'class': 'form-control', 'placeholder': 'Confirm password'}),
        }
  1. views.py
from django.shortcuts import render
from .forms import SignUpForm

def SignupView(request):
    if request.method == 'POST':
        form = SignUpForm(request.POST)
        if form.is_valid():
            user = form.save()
            login(request, user)
            return redirect('home')
    else:
        form = SignUpForm()
    return render(request, 'signup.html', {'form': form})

def LoginView(request):
    return render(request, 'login.html')

  1. signup.html

При выполнении указанного кода я получаю следующий результат для файла signup.html

введите описание изображения здесь

и следующий вывод, который я хочу получить:

введите описание изображения здесь

Обратите внимание на разницу в полях пароля и подтверждения пароля, это и есть проблема.

Форма модели BaseUserCreationForm явно объявляет поля пароля (должна, потому что они не являются частью модели), и вы не можете использовать Meta.widgets, чтобы перезаписать виджет поля формы, которое было явно объявлено. Вы можете перезаписать только те поля, которые были неявно добавлены фабрикой форм модели.
(Да, я согласен, что это странно)

Поля, определенные декларативно, оставляются как есть, поэтому любые настройки, сделанные для мета-атрибутов, таких как виджеты, метки, help_texts или error_messages, игнорируются; они применяются только к полям, которые генерируются автоматически.

Ссылки: django docs и a related SO question

Если вы хотите установить свои собственные виджеты, вам придется объявить поля заново:

class SignUpForm(UserCreationForm):
    password1 = forms.CharField(
        label=_("Password"),
        strip=False,
        widget=forms.PasswordInput(attrs={'class': 'form-control', 'placeholder': 'Enter password'}),
        help_text=password_validation.password_validators_help_text_html(),
    )
    password2 = forms.CharField(
        label=_("Password confirmation"),
        widget=forms.PasswordInput(attrs={'class': 'form-control', 'placeholder': 'Confirm password'}),
        strip=False,
        help_text=_("Enter the same password as before, for verification."),
    )

    class Meta:
        model = CustomUser
        fields = ['first_name', 'last_name', 'email', 'password1', 'password2']
        widgets = {
            'first_name': forms.TextInput(attrs={'class': 'form-control', 'placeholder': 'Enter your first name'}),
            'last_name': forms.TextInput(attrs={'class': 'form-control', 'placeholder': 'Enter your last name'}),
            'email': forms.EmailInput(attrs={'class': 'form-control', 'placeholder': 'Enter your email'}),
        }

forms.py необходимо обновить до следующего:

from django import forms
from django.contrib.auth.forms import UserCreationForm
from django.contrib.auth.models import User
from .models import CustomUser

class SignUpForm(UserCreationForm):
    class Meta:
        model = CustomUser
        fields = ['first_name', 'last_name', 'email', 'password1', 'password2']
        widgets = {
            'first_name': forms.TextInput(attrs={'class': 'form-control', 'placeholder': 'First name'}),
            'last_name': forms.TextInput(attrs={'class': 'form-control', 'placeholder': 'Last name'}),
            'email': forms.EmailInput(attrs={'class': 'form-control', 'placeholder': 'Email'}),
        }
        
    def __init__(self, *args, **kwargs):
        super(SignUpForm, self).__init__(*args, **kwargs)
        
        self.fields['password1'].widget.attrs['class'] = 'form-control'
        self.fields['password1'].widget.attrs['placeholder'] = 'Password'
        self.fields['password2'].widget.attrs['class'] = 'form-control'
        self.fields['password2'].widget.attrs['placeholder'] = 'Confirm Password'

class LoginForm(forms.Form):
    email = forms.EmailField(widget=forms.EmailInput(attrs={'class': 'form-control', 'placeholder': 'Enter your email'}))
    password = forms.CharField(widget=forms.PasswordInput(attrs={'class': 'form-control', 'placeholder': 'Enter your password'}))

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

Вернуться на верх