Django模板不呈现动态表单错误

时间:2015-12-04 17:43:10

标签: django django-models django-forms django-templates

我有一个Django 1.8表单,其中包含一个段落标记,可以呈现一些反馈或用户提交的问题。它还包含一个textarea输入'response_text'和一对单选按钮'close_issue'。此响应输入可用于向用户发送可选响应。如果用户提交了一些反馈,管理员应该能够点击“关闭问题”单选按钮并提交表单而不做任何回复。但是,如果textarea输入包含一个问题,那么表单应该呈现错误,告诉管理员他/她无法在不在响应输入中键入答案的情况下提交表单。我遇到的问题是,如果用户提交了一个问题但管理员没有输入响应,我无法获取表单导致模板呈现错误消息。我的视图,模型,表单和模板如下所示。 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>

2 个答案:

答案 0 :(得分:1)

当您在POST上实例化时,您没有将submission传递给表单,因此永远不会设置所需的属性。

答案 1 :(得分:0)

丹尼尔罗斯曼是正确的,当我在POST上实例化表单时,我需要将'submission'传递给表单。但还有两个问题。首先,我需要在else块中实例化表单。如果未执行此操作且表单未验证,则表示您将未绑定的表单传递回查看器,并且不会显示任何错误。此外,在此处实例化时,没有必要将“提交”传递给表单:

...
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让我重新走上寻找解决方案的道路。