Skip to content

Instantly share code, notes, and snippets.

@neara
Last active June 10, 2024 15:30
Show Gist options
  • Save neara/6209563 to your computer and use it in GitHub Desktop.
Save neara/6209563 to your computer and use it in GitHub Desktop.
Django Class Based Views and Inline Formset Example
from django.forms import ModelForm
from django.forms.models import inlineformset_factory
from models import Sponsor, Sponsorship
class SponsorForm(ModelForm):
class Meta:
model = Sponsor
class SponsorshipForm(ModelForm):
class Meta:
model = Sponsorship
SponsorShipsFormSet = inlineformset_factory(Sponsor, Sponsorship,
form=SponsorshipForm, extra=2)
from django.db import transaction
from django.views.generic import CreateView
from forms import SponsorForm, SponsorShipsFormSet
class CreateSponsor(CreateView):
form_class = SponsorForm
template_name = 'sponsor_form.html'
def get_context_data(self, **kwargs):
data = super(CreateSponsor, self).get_context_data(**kwargs)
if self.request.POST:
data['sponsorships'] = SponsorShipsFormSet(self.request.POST)
else:
data['sponsorships'] = SponsorShipsFormSet()
return data
def form_valid(self, form):
context = self.get_context_data()
sponsorships = context['sponsorships']
with transaction.commit_on_success():
form.instance.created_by = self.request.user
form.instance.updated_by = self.request.user
self.object = form.save()
if sponsorships.is_valid():
sponsorships.instance = self.object
sponsorships.save()
return super(CreateSponsor, self).form_valid(form)
def get_success_url(self):
return reverse('sponsors')
@halfnibble
Copy link

You have save my life. Why isn't this a more obvious process?

BTW, is there any reason you use get_context_data() to instantiate the formset, instead of just doing it directly in form_valid()?

@dmitrysus
Copy link

SponsorMixin? What is that mean?

@rmosolgo
Copy link

Thanks! I had to change this to pass instance=self.object when initializing the formset.

@EmadMokhtar
Copy link

@rmosologo Is the relationship between Sponsor and Sponsorship are one-to-many or one-to-one? and What is SponsorMixin?

@hurta2yaisel
Copy link

What the hell is SponsorMixin?

@MiniGunnR
Copy link

Can I use it for updating multiple entries at the same time? If so, can anyone refer me to a good tutorial?

@koslib
Copy link

koslib commented Jun 4, 2017

Any luck finding how we use this with UpdateView instead of just CreateView, so that we update also stuff?

@tonysyu
Copy link

tonysyu commented Jun 6, 2017

@koslibpro: You can find an example with UpdateView here: https://github.com/timhughes/django-cbv-inline-formset

@miguelcb84
Copy link

miguelcb84 commented Jun 16, 2017

In that case I guess you need to tell the formset to use the instance:

data['sponsorships'] = SponsorShipsFormSet(self.request.POST, instance=self.object)
...
data['sponsorships'] = SponsorShipsFormSet(instance=self.object)

@leonardocintra
Copy link

leonardocintra commented Jun 30, 2017

My site is in error in UpdateView

form show duplicate
image

forms.py

class ExameUrinaRotinaForm(forms.ModelForm):
     
     class Meta:
         model = ExameUrinaRotina
         exclude = ()

ExameUrinaRotinaFormSet = inlineformset_factory(Laudo, ExameUrinaRotina, form=ExameUrinaRotinaForm, extra=1)

views.py

def get_context_data(self, **kwargs):
        context = super(UrinaRotinaUpdate, self).get_context_data(**kwargs)
        if self.request.POST:
            context['form_urina_rotina'] = ExameUrinaRotinaFormSet(self.request.POST, instance=self.object)
            context['form_urina_rotina'].full_clean()
        else:
            context['form_urina_rotina'] = ExameUrinaRotinaFormSet(instance=self.object)
        return context

urina_rotina_update.html

{{ form_urina_rotina.management_form }}

{% for form in form_urina_rotina %}
    <div class="form-group">
        <label class="col-sm-2 control-label">{{ form.volume.label }}</label>
        {{ form.volume }}
    </div>
{% endfor %}

@OmarNour
Copy link

OmarNour commented Sep 6, 2017

can you show us sponsor_form.html ?

@vmonteco
Copy link

vmonteco commented Oct 3, 2017

Interesting and helpful, but is SponsorMixin specific to the case you used for the example or is it specific to the usage of inline_formsets with CreateView?

@surfer190
Copy link

This thing is old now module 'django.db.transaction' has no attribute 'commit_on_success'

@nix1947
Copy link

nix1947 commented Jun 8, 2018

SponsorForm get saved even though SponsorShipsFormSet are invalid

@zypro
Copy link

zypro commented Jul 6, 2018

Maybe this update helps:

    def form_valid(self, form):
        context = self.get_context_data()
        sponsorships = context['sponsorships']
        with transaction.atomic():
            form.instance.created_by = self.request.user
            form.instance.updated_by = self.request.user
            self.object = form.save()
            if sponsorships.is_valid():
                sponsorships.instance = self.object
                sponsorships.save()
        return super(CreateSponsor, self).form_valid(form)

@addohm
Copy link

addohm commented Aug 19, 2019

What the hell is SponsorMixin?

He's not actually using that in his code but it's basically an input parameter.

@yarickprih
Copy link

Do you guys know how to implement update_or_create method for inline model to exclude possibility of adding 2 or more similar instances?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment