В моих формах не отображаются сообщения об ошибках, когда я пытаюсь отправить пустую форму, но я вижу ошибки при циклическом просмотре ошибок поля в 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 Я добавил код, который вы просили. Пожалуйста, дайте мне знать, если вам нужно что-нибудь еще.
Не могли бы вы также добавить код модели MyRegistration, пожалуйста?
А также код вашего просмотра, пожалуйста
@vinkomlacic Я добавил оба запрошенных вами модуля. Пожалуйста, проверьте. Также я заменил код шаблона на обновленный.
Когда вы вызываете 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')
РЕДАКТИРОВАТЬ № 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
.render
для сценариев успеха, только при обработке метода GET или когда вам нужно повторно отобразить форму для отображения ошибок проверки.На самом деле это не помогло. Пробовал рендерить form.non_field_errors , не получилось. Создал отдельные методы clean для каждого поля, но безрезультатно!
Можете ли вы добавить то, что вы видите в ошибках?
Я попробовал это протестировать, и у меня это работает (non_field_errors получить визуализацию). Итак, я подозреваю, что ошибки могут быть в представлениях или коде модели.
Я также добавил правку, касающуюся использования self.instance
Вот в чем проблема, ошибки нет. Форма просто остается нетронутой, когда я отправляю ее совершенно пустой, без ошибок, ничего. Таким образом, здесь невозможно отследить основную проблему.
Я также обновил MyRegistrationForm в своем посте, где я использовал подход clean_data, но безрезультатно. Надеюсь, вы найдете что-то в модели или функции просмотра.
Я обновил ответ, чтобы добавить исправление для метода просмотра.
Я обновил функцию просмотра в своем посте. Пожалуйста, дайте мне знать, если это то, что вы рекомендовали, и если да, то, к сожалению, это тоже не сработало! А по поводу аутентификации пользователя, собственно, новых пользователей может создавать только суперпользователь.
Другой вопрос, будет ли функция сопоставления паролей работать автоматически, когда я создал свою пользовательскую модель, унаследовав AbstractBaseUser, и я не использую UserCreationForm?
Я также хотел бы отметить, что ни одна из форм в моих приложениях не отображает ошибки. Я разместил эту конкретную форму в качестве примера. Если это будет исправлено, возможно, это сделают и другие.
Функция сопоставления паролей зависит от того, что ваши поля названы password1 и password2. Если это правда, то это сработает. Смотрите документы и этот ТАК пост
PS, я не вижу никаких обновлений в исходном сообщении. Является ли текущий код в сообщении тем, что вы пробовали?
У вас все еще есть проблемная строка fm=MyRegistrationForm(). Пожалуйста, попробуйте код, предложенный в ответе.
Я действительно неправильно прочитал эту строку. Теперь это РАБОТАЕТ!! Благодаря тонну!
Можете ли вы добавить код вашей формы тоже?