Django formset doesn't validate

2019-02-09 15:54发布

I am trying to save a formset but it seems to be bypassing is_valid() even though there are required fields.

To test this I have a simple form:

class AlbumForm(forms.Form):
  name = forms.CharField(required=True)

The view:

@login_required
def add_album(request, artist):
  artist = Artist.objects.get(slug__iexact=artist)
  AlbumFormSet = formset_factory(AlbumForm)
  if request.method == 'POST':
    formset = AlbumFormSet(request.POST, request.FILES)
    if formset.is_valid():
      return HttpResponse('worked')
  else:
    formset = AlbumFormSet()
  return render_to_response('submissions/addalbum.html', {
   'artist': artist,
   'formset': formset,
  }, context_instance=RequestContext(request))

And the template:

<form action="" method="post" enctype="multipart/form-data">{% csrf_token %}
{{ formset.management_form }}
{% for form in formset.forms %}
  <ul class="addalbumlist">
    {% for field in form %}
     <li>
        {{ field.label_tag }}
        {{ field }}
        {{ field.errors }}
     </li>
    {% endfor %}
  </ul>
{% endfor %}
   <div class="inpwrap">
    <input type="button" value="add another">
    <input type="submit" value="add">
   </div>
</form>

What ends up happening is I hit "add" without entering a name then HttpResponse('worked') get's called seemingly assuming it's a valid form.

I might be missing something here, but I can't see what's wrong. What I want to happen is, just like any other form if the field is required to spit out an error if its not filled in. Any ideas?

4条回答
乱世女痞
2楼-- · 2019-02-09 16:17

Heh, I was having this exact same problem. The problem is that you're using a formset!! Formsets allow all fields in a form to be blank. If, however, you have 2 fields, and fill out only one, then it will recognize your required stuffs. It does this because formsets are made for "bulk adding" and sometimes you don't want to fill out all the extra forms on a page. Really annoying; you can see my solution here.

查看更多
成全新的幸福
3楼-- · 2019-02-09 16:18

Add 2 lines.

if request.method == 'POST':
  def initial_form_count(self): return 10 # the number of forms
  AlbumFormSet.initial_form_count = initial_form_count
  formset = AlbumFormSet(request.POST, request.FILES)

Good luck!

查看更多
爷、活的狠高调
4楼-- · 2019-02-09 16:37

For each of the fields that are required, add an extra entry in the attrs parameter


    resident_status = forms.ChoiceField(widget=forms.Select(
        attrs={'class': 'form-control', 'required': 'required'}), choices=President.RESIDENT_STATUS,
        required=True)



As you can see, I maintain the required=True for django's form validation but specify 'required':'required' for the template to insist for the field be required.

Hope that helps.

查看更多
冷血范
5楼-- · 2019-02-09 16:43

use:

if not any(formset.errors): ...

instead of:

if formset.is_valid(): ...

查看更多
登录 后发表回答