Opened 7 years ago

Closed 4 years ago

#9538 closed New feature (fixed)

modelformset_factory cannot easily be used for only inserting

Reported by: cgrady Owned by: brosner
Component: Forms Version: 1.3
Severity: Normal Keywords: modelform
Cc: Triage Stage: Accepted
Has patch: no Needs documentation: yes
Needs tests: no Patch needs improvement: no
Easy pickings: no UI/UX: no


I just finished adding multi-file uploading to a little file management app I'm making, and it was far more difficult than it had to be to make it stop showing existing models as well as new forms.

modelformset_factory should have an option to work in add-only mode - I had to make my own subclass of BaseModelFormSet and set the queryset to an empty list to make it stop showing current models, which is quite a hack :)

Change History (9)

comment:1 Changed 7 years ago by brosner

  • Needs documentation unset
  • Needs tests unset
  • Patch needs improvement unset

You don't need to subclass BaseModelFormSet. You can pass in a queryset to the constructor of the formset:

FileFormSet = modelformset_factory(FileModel, extra=3)
formset = FileFormSet(queryset=FileModel.objects.none())

I don't see the point in adding a way to do this outside of just passing in an empty queryset. I would prefer to make a documentation change here.

comment:2 Changed 7 years ago by cgrady

That doesn't seem to work - I tried queryset=Image.objects.none() and queryset=[] and neither changed anything - only my subclass method worked

comment:3 Changed 7 years ago by brosner

  • Needs documentation set
  • Owner changed from nobody to brosner
  • Status changed from new to assigned
  • Triage Stage changed from Unreviewed to Accepted

I took a minute to look into this. I am not seeing any odd behavior with use an empty queryset.

In [1]: from django.forms.models import modelformset_factory

In [2]: from satchmo.apps.product.models import Product

In [3]: FormSet = modelformset_factory(Product, fields=("sku",), extra=3)

In [4]: formset = FormSet(queryset=Product.objects.none())

In [5]: for form in formset.forms:
   ...:     print form.as_p()
<p><label for="id_form-0-sku">SKU:</label> <input id="id_form-0-sku" type="text" name="form-0-sku" maxlength="150" /><input type="hidden" name="form-0-id" id="id_form-0-id" /></p>
<p><label for="id_form-1-sku">SKU:</label> <input id="id_form-1-sku" type="text" name="form-1-sku" maxlength="150" /><input type="hidden" name="form-1-id" id="id_form-1-id" /></p>
<p><label for="id_form-2-sku">SKU:</label> <input id="id_form-2-sku" type="text" name="form-2-sku" maxlength="150" /><input type="hidden" name="form-2-id" id="id_form-2-id" /></p>

It appears to work fine for me. I would recommend creating a new ticket on a specific issue with doing the above. I want to commit a documentation fix for this however since it seems like a worthy item to document.

comment:4 Changed 6 years ago by anonymous

I think I have a similiar problem. queryset=Subscriber.objects.none() works fine and it displays no initial data in form creation but if you try to save a (empty) formset, the formset tries to validate the same count of rows as the model have.

Uh? Here is a screenshot: The Subscriber model has 6 entries which the formset tries to "compare".

    SubscriberFormSet = modelformset_factory(Subscriber, max_num=0, extra=10,
        fields=('active', 'salutation', 'first_name', 'last_name', 'email',))

    formset = SubscriberFormSet(queryset=Subscriber.objects.none())
    if request.method == 'POST':
        formset = SubscriberFormSet(request.POST)
        if formset.is_valid():

comment:5 Changed 6 years ago by bartTC

Ignore my comment, I've forgot the queryset=Subscriber.objects.none() in the second SubscriberFormSet() instance. Works fine.

comment:6 Changed 5 years ago by lukeplant

  • Severity set to Normal
  • Type set to New feature

comment:7 Changed 4 years ago by claudep

  • Easy pickings unset
  • Resolution set to fixed
  • Status changed from assigned to closed
  • UI/UX unset

I think the docs are pretty clear on this matter currently:

   If you want to return a formset that doesn't include any pre-existing instances of the model, you can specify an empty QuerySet:

   >>> AuthorFormSet(queryset=Author.objects.none())

Hence closing this ticket.

comment:8 Changed 4 years ago by drgubuntu@…

  • Keywords modelform added
  • Resolution fixed deleted
  • Status changed from closed to reopened
  • Version changed from 1.0 to 1.3

Ive got error in this sample program CSRF verification failed. Request aborted.

from myform.xforms.models import Author
from django.forms.models import modelformset_factory
from django.shortcuts import render_to_response, get_object_or_404,HttpResponse

def index(request):

AuthorFormSet = modelformset_factory(Author)

if request.method == 'POST':

formset = AuthorFormSet(request.POST,request.FILES)
if formset.is_valid():


formset = AuthorFormSet()

return render_to_response("authors.html",{"formset":formset,})

# Create your views here.

comment:9 Changed 4 years ago by aaugustin

  • Resolution set to fixed
  • Status changed from reopened to closed

This is a CSRF verification problem, and it doesn't look related to the problem originally described by this ticket.

I suggest reviewing the CSRF docs, and if you can't figure out what's going wrong, asking for help on the #django IRC channel or the django-users mailing list.

Note: See TracTickets for help on using tickets.
Back to Top