Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Limit Django's inlineformset_factory to only create new objects

I am using django's inline formset factory. To use the example in the docs,

author = Author.objects.get(pk=1)
BookFormSet = inlineformset_factory(Author, Book)
formset = BookFormSet(request.POST, instance=author)

will create an inline formset to edit books by a particular author.

I want to create a formset that only allows users to add new books by that author, not edit existing books. Is there a simple way to use inlineformset_factory to do this?

like image 662
Alasdair Avatar asked Mar 01 '10 11:03

Alasdair


2 Answers

inlineformset_factory takes a formset kwarg, which defaults to BaseInlineFormSet. BaseInlineFormSet subclasses BaseModelFormSet, which defines a get_queryset method. If you create a BaseInlineFormSet subclass and override get_queryset to return EmptyQuerySet(), you should get what you're after. In the above example then, it would look like this:

from django.db.models.query import EmptyQuerySet
from django.forms.models import BaseInlineFormSet

class BaseInlineAddOnlyFormSet(BaseInlineFormSet):
    def get_queryset(self):
        return EmptyQuerySet()

author = Author.objects.get(pk=1)
BookFormSet = inlineformset_factory(Author, Book, formset=BaseInlineAddOnlyFormSet)
formset = BookFormSet(request.POST, instance=author)
like image 115
Jeremy Lewis Avatar answered Oct 11 '22 12:10

Jeremy Lewis


Based on Jeremy Lewis and if you don't want to subclass BaseInlineFormSet, you can just give an empty queryset parameter to your BookFormSet.

See pseudo (untested) Django 1.6 code sample:

BookFormSet = inlineformset_factory(parent=Author, model=Book)
if request.method == "POST":
    formset = BookFormSet(request.POST, request.FILES, instance=author)
    if formset.is_valid():
        formset.save()
else:
    queryset = Book.objects.none() # does not allow to edit books
    formset = BookFormSet(instance=project, initial=initial, queryset=queryset)
return render(request, "add_book.html", { "formset": formset, })
like image 3
Andre Miras Avatar answered Oct 11 '22 13:10

Andre Miras