Using Django CreateView to process a formset - it doesn't validate


I am trying to change the view of the CreateView class to handle a set of forms instead of a form.

When the client makes a GET request, the format is displayed to the client correctly. The problem is that the client is submitting the form using POST.

When Django receives a POST, it lands at form_invalid () and form.errors says that this field is needed for the length and name field.

class Service(models.Model):
        (15, '15 minutes'),
        (30, '30 minutes'),
    length = models.FloatField(choices=TIME_CHOICES,max_length=6)
    name = models.CharField(max_length=40)

class ServiceForm(ModelForm):
    class Meta:
        model = Service

ServiceFormSet = modelformset_factory(Service,form=ServiceForm)

class ServiceEditView(CreateView):
    template_name = "service_formset.html"
    model = Service
    form_class = ServiceForm
    success_url = 'works/'

    def form_valid(self, form):
        context = self.get_context_data()
        formset = context['formset']
        if formset.is_valid():
            self.object =
            return HttpResponseRedirect('works/')
            return HttpResponseRedirect('doesnt-work/')

    def form_invalid(self, form):
        print form.errors
        return HttpResponseRedirect('doesnt-work/')

    def get_context_data(self, **kwargs):
        context = super(ServiceEditView, self).get_context_data(**kwargs)

        if self.request.POST:
            context['formset'] = ServiceFormSet(self.request.POST)
            context['formset'] = ServiceFormSet(queryset=Service.objects.filter(
        return context


My question

How can I use createview to handle a set of forms? What am I missing to make sure this is validated correctly?

In the tutorial, I took most of the bits from

In short, what I have done so far

Since the variable form.errors says that every field is required, I think it is expecting a regular form and not a form -> I am missing any option that tells CreateView this is a set of forms.

I've also tried the solution suggested here: .

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


But that didn't matter.


source to share

2 answers


pip install django-extra-views

And in

from extra_views import FormSetView
class ItemFormSetView(ModelFormSetView):
    model = Service
    template_name = 'service_formset.html'


There is a discussion about how to do this in Django core, but the discussions seem to have stalled.

Where I found the solution

This repository has a view called ModelFormSetView that does exactly what I need. It's a class-based view that does the same thing as CreateView, but for forms.



Django go to form_invalid () and form.errors says this field is needed for length and name field.

This is ok and because of the required paramatere field :

By default, every Field class assumes that this value is needed, so if you pass in an empty value - either None or an empty string ("") - then clean () will throw a ValidationError exception:

If you want to reverse this, you can set required = False :

class Service(models.Model):
        (15, '15 minutes'),
        (30, '30 minutes'),
    length = models.FloatField(choices=TIME_CHOICES,max_length=6, required=False)
    name = models.CharField(max_length=40, required=False)


What am I missing to make sure this is validated correctly

Have you tried to post a form with names and .



All Articles