Как отображать сообщения об ошибках, если я не перебираю поля формы в шаблонах Django?

В моих формах не отображаются сообщения об ошибках, когда я пытаюсь отправить пустую форму, но я вижу ошибки при циклическом просмотре ошибок поля в views.py. Как мне преодолеть эту проблему?

Template (обновлено):

    {% block formcontent %}
    {{form.non_field_errors}}
    <div class = "row">
        <div class = "col">
            {{form.username.label_tag}} {{form.username}} {{form.username.errors|striptags}}
        </div>
    </div><br>
    <div class = "row">
        <div class = "col">
            {{form.first_name.label_tag}} {{form.first_name}} {{form.first_name.errors|striptags}}
        </div>
        <div class = "col">
            {{form.last_name.label_tag}} {{form.last_name}} {{form.last_name.errors|striptags}}
        </div>
    </div><br>
    <div class = "row">
        <div class = "col">
            {{form.email.label_tag}} {{form.email}} {{form.email.errors|striptags}}
        </div>
    </div><br>
    <div class = "row">
        <div class = "col">
            {{form.location.label_tag}} {{form.location}} {{form.location.errors|striptags}}
        </div>
        <div class = "col">
            {{form.designation.label_tag}} {{form.designation}} {{form.designation.errors|striptags}}
        </div>
    </div><br>
    <div class = "row">
        <div class = "col">
            {{form.password1.label_tag}} {{form.password1}} {{form.password1.errors|striptags}}
        </div>
        <div class = "col">
            {{form.password2.label_tag}} {{form.password2}} {{form.password2.errors|striptags}}
        </div>
    </div><br>
{% endblock formcontent %}

Редактировать 1: (обновлено)

class MyRegistrationForm(UserCreationForm):
password1=forms.CharField(label='Password', widget=forms.PasswordInput(attrs = {'class':'form-control'}))
password2=forms.CharField(label='Confirm Password', widget=forms.PasswordInput(attrs = {'class':'form-control'}))
class Meta:
    model=MyRegistration
    fields=['username', 'first_name', 'last_name', 'email', 'location', 'designation']
    widgets = {
        'username':forms.TextInput(attrs = {'class':'form-control'}),
        'first_name':forms.TextInput(attrs = {'class':'form-control'}),
        'last_name':forms.TextInput(attrs = {'class':'form-control'}),
        'email':forms.EmailInput(attrs = {'class':'form-control'}),
        'location':forms.Select(attrs = {'class':'form-select'}),
        'designation':forms.TextInput(attrs = {'class':'form-control'}),
    }

def clean_username(self):
    username = self.cleaned_data.get('username')
    if not username:
        raise ValidationError('Username is required!')
    else:
        try:
            MyRegistration.objects.get(username=username)
            raise ValidationError('This username already exists!', code='username_exists')
        except MyRegistration.DoesNotExist:
            pass
    return username

def clean_email(self):
    email=self.cleaned_data.get('email')
    if not email:
        raise ValidationError('Email is required!')
    else:
        try:
            MyRegistration.objects.get(email=email)
            raise ValidationError('This email already exists!', code='email_exists')
        except MyRegistration.DoesNotExist:
            pass
    return email

def clean_first_name(self):
    first_name=self.cleaned_data.get('first_name')
    if not first_name:
        raise ValidationError('First-name is required!')
    return first_name

def clean_last_name(self):
    last_name=self.cleaned_data.get('last_name')
    if not last_name:
        raise ValidationError('Last-name is required!')
    return last_name

def clean_location(self):
    location=self.cleaned_data.get('location')
    if not location:
        raise ValidationError('Location is required!')
    return location

def clean_designation(self):
    designation=self.cleaned_data.get('designation')
    if not designation:
        raise ValidationError('Designation is required!')
    return designation

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

Редактировать 2:

Модели.ру:

class MyRegistration(AbstractBaseUser, PermissionsMixin):
    location_list=[
        ('Solapur', 'Solapur'),
        ('Dhule', 'Dhule'),
        ('Other', 'Other'),
        ]
    username=models.CharField(max_length=10, unique=True)
    email=models.EmailField(unique=True)
    first_name=models.CharField(max_length=150)
    last_name=models.CharField(max_length=150)
    location=models.CharField(max_length=10, choices=location_list, default=None)
    designation=models.CharField(max_length=70)
    is_active=models.BooleanField()
    is_staff=models.BooleanField(default=False)
    start_date=models.DateTimeField(default=timezone.now)
    last_login=models.DateTimeField(null=True)


    USERNAME_FIELD='username'
    REQUIRED_FIELDS=['email', 'first_name', 'last_name', 'location', 'designation']
    objects=FirstManager()
    def __str__(self):
        return self.first_name

Views.py: (обновлено)

def signup(request):
print('1')
if request.user.is_authenticated:
    print('2')
    if request.method=='POST':
        print('3')
        if request.POST.get('password1')==request.POST.get('password2'):
            print('4')
            fm=MyRegistrationForm(request.POST)
            for field in fm:
                print("Field Error:", field.name,  field.errors)
            if fm.is_valid():
                print('6')
                fm.save()
                messages.success(request, 'Registered successfully!!')
            fm=MyRegistrationForm()
            print('7')
            cur_user=request.user
            return render(request, 'account/signup.html', {'form':fm, 'cur_user':cur_user})
    else:
        fm=MyRegistrationForm()
        cur_user=request.user
        return render(request, 'account/signup.html', {'form':fm, 'cur_user':cur_user})
else:
    return HttpResponseRedirect('/')

Можете ли вы добавить код вашей формы тоже?

vinkomlacic 14.01.2023 14:08

@vinkomlacic Я добавил код, который вы просили. Пожалуйста, дайте мне знать, если вам нужно что-нибудь еще.

noob87 14.01.2023 23:50

Не могли бы вы также добавить код модели MyRegistration, пожалуйста?

vinkomlacic 15.01.2023 11:48

А также код вашего просмотра, пожалуйста

vinkomlacic 15.01.2023 11:55

@vinkomlacic Я добавил оба запрошенных вами модуля. Пожалуйста, проверьте. Также я заменил код шаблона на обновленный.

noob87 15.01.2023 19:33
Типы данных JavaScript
Типы данных JavaScript
В JavaScript существует несколько типов данных, включая примитивные типы данных и ссылочные типы данных. Вот краткое объяснение различных типов данных...
Как сделать движок для футбольного матча? (простой вариант)
Как сделать движок для футбольного матча? (простой вариант)
Футбол. Для многих людей, живущих на земле, эта игра - больше, чем просто спорт. И эти люди всегда мечтают стать футболистом или менеджером. Но, к...
Знайте свои исключения!
Знайте свои исключения!
В Java исключение - это событие, возникающее во время выполнения программы, которое нарушает нормальный ход выполнения инструкций программы. Когда...
CSS Flex: что должен знать каждый разработчик
CSS Flex: что должен знать каждый разработчик
CSS Flex: что должен знать каждый разработчик Модуль flexbox, также известный как гибкий модуль разметки box, помогает эффективно проектировать и...
Введение в раздел &quot;Заголовок&quot; в HTML
Введение в раздел "Заголовок" в HTML
Говорят, что лучшее о человеке можно увидеть только изнутри, и это относится и к веб-страницам HTML! Причина, по которой некоторые веб-страницы не...
1
5
92
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Когда вы вызываете ValidationError в методе clean, эти ошибки добавляются к атрибуту non_field_errors в форме. Вот почему ничего не отображается при использовании form.email.errors и других атрибутов errors в определенных полях.

Вы должны визуализировать form.non_field_errors перед визуализацией формы, чтобы вы могли видеть и эти ошибки.

Однако, чтобы решить вашу проблему, я бы предпочел разделить проверку каждого поля на отдельные методы clean_<field_name>. Например, для поля имени пользователя:

def clean_username(self):
    username = self.cleaned_data.get('username')
    if not username:
        raise ValidationError('Username is required!')
    else:
        try:
            un=MyRegistration.objects.get(username=self.instance.username)
            raise ValidationError('This username already exists!')
        except MyRegistration.DoesNotExist:
            pass

    # Make sure you return the value of the data in 
    # the clean_<field_name> methods
    return username

И так далее по другим полям тоже. Выполнение только этого должно исправить ваш код, но вот некоторые другие рекомендации:

  • Используйте коды при повышении ValidationErrors. Например: raise ValidationError('This username already exists', code='username_exists')
  • Проверьте пакет django-crispy, он может обрабатывать HTML-рендеринг форм с минимальным кодом.
  • Вы можете установить ограничения в моделях для уникальных полей (например, имя пользователя) и обязательных полей. Это также не позволяет пользователям, которые не добавляют данные в вашу форму (например, администратору), добавлять повторяющиеся имена пользователей или нулевые значения. Это также будет означать, что большая часть вашего пользовательского кода проверки будет ненужной.

РЕДАКТИРОВАТЬ № 1: Использование instance для получения значений из отправленной формы неверно. Поскольку эта форма используется исключительно для целей создания, поскольку регистрация — это создание нового пользователя, instance всегда будет пустым. instance заполняется данными только при обновлении экземпляра модели.

Вы должны заменить использование instance получением данных формы из self.cleaned_data dict. Например:

# Instead of:
username = self.instance.username
# Use:
username = self.cleaned_data.get('username')

РЕДАКТИРОВАТЬ № 2: После автор добавил код просмотра.

Проблема может быть в вашем коде просмотра. Кроме того, нет необходимости сравнивать password1 и password2, поскольку UserCreationForm уже делает это за вас.

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

def signup(request):
    print('1')
    if request.user.is_authenticated:
        print('2')
        if request.method=='POST':
            print('3')
            form = MyRegistrationForm(request.POST)
            if form.is_valid():
                print('4')
                form.save()
                messages.success(request, 'Registered successfully!!')
            # If you do this, you always render the empty form
            # without the errors
            # fm=MyRegistrationForm()
            print('7')
            cur_user=request.user
            return render(
                request, 'account/signup.html', 
                {'form': form, 'cur_user':cur_user}
            )
        else:
            form = MyRegistrationForm()
            cur_user=request.user
            return render(
                request, 'account/signup.html', 
                {'form':form, 'cur_user':cur_user}
            )
    else:
        return HttpResponseRedirect('/')

Некоторые другие рекомендации:

  • Вам, вероятно, не нужно проверять, аутентифицирован ли пользователь, если это представление регистрации. Как новые пользователи могут создать учетную запись? Однако, если это необходимо, вероятно, для этого лучше подойдет декоратор @login_required.
  • В случае успеха вам необходимо перенаправить на URL-адрес успеха. Не используйте render для сценариев успеха, только при обработке метода GET или когда вам нужно повторно отобразить форму для отображения ошибок проверки.

На самом деле это не помогло. Пробовал рендерить form.non_field_errors , не получилось. Создал отдельные методы clean для каждого поля, но безрезультатно!

noob87 15.01.2023 02:56

Можете ли вы добавить то, что вы видите в ошибках?

vinkomlacic 15.01.2023 10:26

Я попробовал это протестировать, и у меня это работает (non_field_errors получить визуализацию). Итак, я подозреваю, что ошибки могут быть в представлениях или коде модели.

vinkomlacic 15.01.2023 12:00

Я также добавил правку, касающуюся использования self.instance

vinkomlacic 15.01.2023 12:06

Вот в чем проблема, ошибки нет. Форма просто остается нетронутой, когда я отправляю ее совершенно пустой, без ошибок, ничего. Таким образом, здесь невозможно отследить основную проблему.

noob87 15.01.2023 19:42

Я также обновил MyRegistrationForm в своем посте, где я использовал подход clean_data, но безрезультатно. Надеюсь, вы найдете что-то в модели или функции просмотра.

noob87 15.01.2023 19:47

Я обновил ответ, чтобы добавить исправление для метода просмотра.

vinkomlacic 15.01.2023 21:15

Я обновил функцию просмотра в своем посте. Пожалуйста, дайте мне знать, если это то, что вы рекомендовали, и если да, то, к сожалению, это тоже не сработало! А по поводу аутентификации пользователя, собственно, новых пользователей может создавать только суперпользователь.

noob87 16.01.2023 03:35

Другой вопрос, будет ли функция сопоставления паролей работать автоматически, когда я создал свою пользовательскую модель, унаследовав AbstractBaseUser, и я не использую UserCreationForm?

noob87 16.01.2023 03:39

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

noob87 16.01.2023 03:47

Функция сопоставления паролей зависит от того, что ваши поля названы password1 и password2. Если это правда, то это сработает. Смотрите документы и этот ТАК пост

vinkomlacic 16.01.2023 09:14

PS, я не вижу никаких обновлений в исходном сообщении. Является ли текущий код в сообщении тем, что вы пробовали?

vinkomlacic 16.01.2023 09:15

У вас все еще есть проблемная строка fm=MyRegistrationForm(). Пожалуйста, попробуйте код, предложенный в ответе.

vinkomlacic 16.01.2023 11:28

Я действительно неправильно прочитал эту строку. Теперь это РАБОТАЕТ!! Благодаря тонну!

noob87 16.01.2023 12:07

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