Opened 15 years ago

Closed 12 years ago

#9538 closed New feature (fixed)

modelformset_factory cannot easily be used for only inserting

Reported by: Collin Grady Owned by: Brian Rosner
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

Description

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 by Brian Rosner, 15 years ago

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 by Collin Grady, 15 years ago

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 by Brian Rosner, 15 years ago

Needs documentation: set
Owner: changed from nobody to Brian Rosner
Status: newassigned
Triage Stage: UnreviewedAccepted

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 by anonymous, 15 years ago

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: http://img.mahner.org/formerror-20090602-165834.jpg 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():
           formset.save(commit=False)

comment:5 by Martin Mahner, 15 years ago

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

comment:6 by Luke Plant, 13 years ago

Severity: Normal
Type: New feature

comment:7 by Claude Paroz, 12 years ago

Easy pickings: unset
Resolution: fixed
Status: assignedclosed
UI/UX: unset

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

https://docs.djangoproject.com/en/1.3/topics/forms/modelforms/#changing-the-queryset

   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 by drgubuntu@…, 12 years ago

Keywords: modelform added
Resolution: fixed
Status: closedreopened
Version: 1.01.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.save()

else:

formset = AuthorFormSet()

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


# Create your views here.

comment:9 by Aymeric Augustin, 12 years ago

Resolution: fixed
Status: reopenedclosed

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