没有使用Django Crispy Forms渲染的Formset的非表单错误

时间:2015-04-01 20:51:30

标签: django-forms django-crispy-forms formsets

我实现了一个自定义的clean方法来验证我的formset。我知道有错误,因为我可以将它们打印到控制台,但这些non_form_errors()永远不会在我的模板中呈现。我该如何渲染它们?

template.html:

<form action="{% url 'databank:register' %}" method="post" enctype="multipart/form-data">
  {% csrf_token %}

  <div class="container">
    <div class="row" style="margin-top: 30px"> 
      <div class="col-md-10 col-md-offset-1">
        {{ dataset_form.media }}
        {% crispy dataset_form %}
          <div class="authorFormset">
            {% for form in formset %}
              {% crispy form helper %}
            {% endfor %}    
          </div>
        {% crispy terms_form %}
      </div>
    </div>
  </div>

  <div class="container">
    <div class="row">
      <div class="col-md-10 col-md-offset-1">
        <input type="submit" class="btn btn-lg btn-success" value="Submit">
      </div>
    </div>
</div>
{{ formset.management_form }}

forms.py:

class BaseAuthorFormset(BaseFormSet):
    def clean(self):   
        if any(self.errors):
            return
        roles = []
        for form in self.forms:
            contributor_role = form.cleaned_data['role']
            for x in contributor_role:
                if (x == "Depositor") and (x in roles):
                    raise forms.ValidationError("Only one Contributor may be marked Depositor.")
                roles.append(x)
            if "Depositor" not in roles:
                raise forms.ValidationError("You must designate one Contributor as Depositor.")

    def __init__(self, *args, **kwargs):
        super(BaseAuthorFormset, self).__init__(*args, **kwargs)
        for form in self.forms:
            form.empty_permitted = False

class AuthorForm(forms.Form):

    first_name = forms.CharField(
        max_length=96,
        required=True,
    )

    middle_initial = forms.CharField(
        max_length=96,
        required=False,
    )

    last_name = forms.CharField(
    max_length = 96,
    required = True,
    )

    email = forms.EmailField(
        required = True
    )

    role = forms.ModelMultipleChoiceField(
        queryset=AuthorRole.objects.filter(is_visible=True),
        widget=forms.CheckboxSelectMultiple,
        required = False,
    )

    affiliation = forms.CharField(
        max_length=512,
        required=True,
    )


AuthorFormset = formset_factory(AuthorForm, formset=BaseAuthorFormset, extra=1)

class AuthorFormHelper(FormHelper):

    def __init__(self, *args, **kwargs):
        super(AuthorFormHelper, self).__init__(*args, **kwargs)
        self.helper = FormHelper()
        FormHelper.form_tag = False
        FormHelper.disable_csrf = True
        FormHelper.formset_error_title = "Contributor Errors"
        self.layout = Layout(
            Div(
                Div( HTML("<h4>Contributor</h4>"),
                    Div(
                        Div('first_name', css_class='col-xs-4'),
                        Div('middle_initial', css_class='col-xs-4'),
                        Div('last_name', css_class='col-xs-4'),
                        css_class='row'
                    ),
                    Div(
                        Div('affiliation', css_class='col-xs-12 col-sm-6'),
                        Div('email', css_class='col-xs-12 col-sm-6'),
                        Div(
                            Field(
                                InlineCheckboxes('role'),
                            ), 
                            css_class='col-xs-12 col-sm-6'),
                        css_class='row'
                    ),
                ),
                css_class = 'add_author',
                id="authorFormDiv"
            ),
        )

2 个答案:

答案 0 :(得分:2)

经过大量调查后,我发现了原生non_form_errors过滤器在模板中渲染BaseInlineFormSet脆弱django-crispy的解决方案。也许这对某人有帮助(至少在django-crispy-forms == 1.5.2,Django == 1.6)中有效:

{% load crispy_forms_filters %}
{% if formset.non_form_errors %}
    {{ formset|as_crispy_errors }}
{% endif %}

答案 1 :(得分:1)

感谢@Brandon帮我解决这个问题!

在视图中,formset.__dict__可用于打印对象本身以确定存储错误的位置。这样做表明使用_non_form_errors密钥存储了formset错误。然后我将这些错误传递给模板!