Django 模板不呈现动态表单错误
Django template isn't rendering dynamic form errors
我有一个 Django 1.8 表单,其中包含一个段落标记,该标记呈现用户提交的一些反馈或问题。它还包含一个文本输入 'response_text' 和一对单选按钮 'close_issue'。此响应输入可用于向用户发送可选响应。如果用户提交了一些反馈,管理员应该能够单击 'close issue' 单选按钮并提交表单而无需回复。但是,如果 textarea 输入包含问题,则表单应呈现错误,告诉管理员 he/she 必须在响应输入中键入答案才能提交表单。我遇到的问题是,如果用户提交了问题但管理员没有输入回复,我无法获取表单以导致模板呈现错误消息。我的视图、模型、表单和模板如下所示。 forms.py 显示所有方式(全部注释掉) 如果用户提交问题,我尝试将响应输入字段设为必填,以便模板显示错误。我还尝试用一种方法覆盖默认的 'clean' 方法,如果用户提交了一个问题并且响应输入为空白,但这种方法也不起作用,则会引发 ValidationError。谁能告诉我我做错了什么?
谢谢。
# view.py
def review_feedback_or_question(request, template, *args, **kwargs):
fqid = kwargs['fqid']## Heading ##
submission = FeedbackQuestion.objects.get(pk=fqid)
if request.method == 'POST':
form = FeedbackQuestionResponseForm(request.POST, submission=submission)
if form.is_valid():
# process the form
return redirect('review-feedback-or-question-queue')
else:
pass
form = FeedbackQuestionResponseForm(submission=submission)
context = {'form': form, 'submission': submission,}
return render(request, template, context)
# models.py
class FeedbackQuestion(models.Model):
SELECT = ''
FEEDBACK = 'feedback'
QUESTION = 'question'
SUBMISSION_TYPE_CHOICES = (
(SELECT , '-- Select --'),
(FEEDBACK, 'Feedback'),
(QUESTION, 'Question'),
)
user = models.ForeignKey(User, related_name="user")
submission_type = models.CharField(max_length=8,
choices=SUBMISSION_TYPE_CHOICES,
default=SELECT)
submission_text = models.TextField()
date_submitted = models.DateTimeField(auto_now_add=True)
response_text = models.TextField()
respondent = models.ForeignKey(User, related_name='respondent')
date_responded = models.DateTimeField(auto_now=True)
issue_closed = models.BooleanField(default=False)
class Meta:
db_table = 'feedback_question'
# forms.py
class FeedbackQuestionResponseForm(forms.Form):
TRUE = 1
FALSE = 0
BLANK = ''
CHOICES = ( (TRUE, 'Yes'), (FALSE, 'No') )
response_text = forms.CharField(
required=False,
label='',
widget=forms.Textarea(attrs={'placeholder': 'Enter response...'}))
close_issue = forms.TypedChoiceField(
choices=CHOICES,
label='Close this issue?',
widget=forms.RadioSelect(renderer=HorizontalRadioRenderer),
coerce=int)
def __init__(self, *args, **kwargs):
if 'submission' in kwargs:
submission = kwargs.pop('submission')
if submission.submission_type == 'question':
# NONE OF THESE WORKED!
#self.fields.get('response_text').required = True
#self.declared_fields['response_text'].required = self.TRUE
#self.declared_fields['response_text'].required = self.TRUE
#self.declared_fields['response_text'].required = True
#self._errors['response_text'] = "You must enter a response"
pass
super(FeedbackQuestionResponseForm, self).__init__(*args, **kwargs)
# template.html
<p>{{ submission.submission_text }}</p>
<form action="" method="post">{% csrf_token %}
{{ form.non_field_errors }}
{% if form.errors %}
{% if form.errors.items|length == 1 %}
Please correct the error below.
{% else %}
Please correct the errors below.
{% endif %}
</p>
{% endif %}
{{ form.response_text.errors }}
{{ form.response_text.label_tag }} {{ form.response_text }}
{{ form.close_issue.errors }}
{{ form.close_issue }} {{ form.close_issue.label_tag }}
<input type="submit" value="Submit" class="" />
</form>
当您在 POST 上实例化它时,您没有将 submission
传递到表单中,因此永远不会设置所需的属性。
Daniel Roseman 是正确的,当我在 POST 上实例化表单时,我需要将 'submission' 传递到表单中。但是还有另外两个问题。首先,我需要在 else 块中实例化表单。如果这没有完成并且表单没有验证,那么您将未绑定的表单传递回查看器并且不会显示任何错误。此外,在此处实例化时,无需将 'submission' 传递给表单:
...
else:
form = FeedbackQuestionResponseForm()
context = {...}
...
下一个问题是我在 init 方法中的语句顺序不正确。看来我需要在尝试引用 'response_text' 字段之前执行 'super()' 。我需要在 Django 源代码中找到并研究这个方法,才能准确理解原因。无论如何,这有效:
def __init__(self, *args, **kwargs):
if 'submission' in kwargs:
submission = kwargs.pop('submission')
else:
submission = False
super(FeedbackQuestionResponseForm, self).__init__(*args, **kwargs)
if submission:
if submission.submission_type == 'question':
self.fields['response_text'].required = True
else:
self.fields['response_text'].required = False
实施上述更改后,如果用户提交问题,表单将使 response_text 字段成为必填字段,如果管理员在提交表单之前未输入回复,则会显示错误。再次感谢 Daniel 让我回到寻找解决方案的正轨。
我有一个 Django 1.8 表单,其中包含一个段落标记,该标记呈现用户提交的一些反馈或问题。它还包含一个文本输入 'response_text' 和一对单选按钮 'close_issue'。此响应输入可用于向用户发送可选响应。如果用户提交了一些反馈,管理员应该能够单击 'close issue' 单选按钮并提交表单而无需回复。但是,如果 textarea 输入包含问题,则表单应呈现错误,告诉管理员 he/she 必须在响应输入中键入答案才能提交表单。我遇到的问题是,如果用户提交了问题但管理员没有输入回复,我无法获取表单以导致模板呈现错误消息。我的视图、模型、表单和模板如下所示。 forms.py 显示所有方式(全部注释掉) 如果用户提交问题,我尝试将响应输入字段设为必填,以便模板显示错误。我还尝试用一种方法覆盖默认的 'clean' 方法,如果用户提交了一个问题并且响应输入为空白,但这种方法也不起作用,则会引发 ValidationError。谁能告诉我我做错了什么?
谢谢。
# view.py
def review_feedback_or_question(request, template, *args, **kwargs):
fqid = kwargs['fqid']## Heading ##
submission = FeedbackQuestion.objects.get(pk=fqid)
if request.method == 'POST':
form = FeedbackQuestionResponseForm(request.POST, submission=submission)
if form.is_valid():
# process the form
return redirect('review-feedback-or-question-queue')
else:
pass
form = FeedbackQuestionResponseForm(submission=submission)
context = {'form': form, 'submission': submission,}
return render(request, template, context)
# models.py
class FeedbackQuestion(models.Model):
SELECT = ''
FEEDBACK = 'feedback'
QUESTION = 'question'
SUBMISSION_TYPE_CHOICES = (
(SELECT , '-- Select --'),
(FEEDBACK, 'Feedback'),
(QUESTION, 'Question'),
)
user = models.ForeignKey(User, related_name="user")
submission_type = models.CharField(max_length=8,
choices=SUBMISSION_TYPE_CHOICES,
default=SELECT)
submission_text = models.TextField()
date_submitted = models.DateTimeField(auto_now_add=True)
response_text = models.TextField()
respondent = models.ForeignKey(User, related_name='respondent')
date_responded = models.DateTimeField(auto_now=True)
issue_closed = models.BooleanField(default=False)
class Meta:
db_table = 'feedback_question'
# forms.py
class FeedbackQuestionResponseForm(forms.Form):
TRUE = 1
FALSE = 0
BLANK = ''
CHOICES = ( (TRUE, 'Yes'), (FALSE, 'No') )
response_text = forms.CharField(
required=False,
label='',
widget=forms.Textarea(attrs={'placeholder': 'Enter response...'}))
close_issue = forms.TypedChoiceField(
choices=CHOICES,
label='Close this issue?',
widget=forms.RadioSelect(renderer=HorizontalRadioRenderer),
coerce=int)
def __init__(self, *args, **kwargs):
if 'submission' in kwargs:
submission = kwargs.pop('submission')
if submission.submission_type == 'question':
# NONE OF THESE WORKED!
#self.fields.get('response_text').required = True
#self.declared_fields['response_text'].required = self.TRUE
#self.declared_fields['response_text'].required = self.TRUE
#self.declared_fields['response_text'].required = True
#self._errors['response_text'] = "You must enter a response"
pass
super(FeedbackQuestionResponseForm, self).__init__(*args, **kwargs)
# template.html
<p>{{ submission.submission_text }}</p>
<form action="" method="post">{% csrf_token %}
{{ form.non_field_errors }}
{% if form.errors %}
{% if form.errors.items|length == 1 %}
Please correct the error below.
{% else %}
Please correct the errors below.
{% endif %}
</p>
{% endif %}
{{ form.response_text.errors }}
{{ form.response_text.label_tag }} {{ form.response_text }}
{{ form.close_issue.errors }}
{{ form.close_issue }} {{ form.close_issue.label_tag }}
<input type="submit" value="Submit" class="" />
</form>
当您在 POST 上实例化它时,您没有将 submission
传递到表单中,因此永远不会设置所需的属性。
Daniel Roseman 是正确的,当我在 POST 上实例化表单时,我需要将 'submission' 传递到表单中。但是还有另外两个问题。首先,我需要在 else 块中实例化表单。如果这没有完成并且表单没有验证,那么您将未绑定的表单传递回查看器并且不会显示任何错误。此外,在此处实例化时,无需将 'submission' 传递给表单:
...
else:
form = FeedbackQuestionResponseForm()
context = {...}
...
下一个问题是我在 init 方法中的语句顺序不正确。看来我需要在尝试引用 'response_text' 字段之前执行 'super()' 。我需要在 Django 源代码中找到并研究这个方法,才能准确理解原因。无论如何,这有效:
def __init__(self, *args, **kwargs):
if 'submission' in kwargs:
submission = kwargs.pop('submission')
else:
submission = False
super(FeedbackQuestionResponseForm, self).__init__(*args, **kwargs)
if submission:
if submission.submission_type == 'question':
self.fields['response_text'].required = True
else:
self.fields['response_text'].required = False
实施上述更改后,如果用户提交问题,表单将使 response_text 字段成为必填字段,如果管理员在提交表单之前未输入回复,则会显示错误。再次感谢 Daniel 让我回到寻找解决方案的正轨。