Populate formset with information from db

602 Views Asked by At

I have a view where the user should be able to update an instance of a model, and also update or create new instances of a model related to the first one. I tryied using formsets to do this, and it works perfeclty for creating new objects, but i'm not finding a way to show the objects that already have been created. My problem is that i don't know how to populate the formsets with the existing data, so that i can put it in the context

So this are my models:

class Order(Model):
...

class invoice(Model):
    order = models.ForeignKey(Order)
...

And my view is something like this:

class OrderDetailView(UpdateView):
    invoice_form_class = InvoiceForm

    def get_context_data(self, **kwargs):
        context = super(OrderDetailView, self).get_context_data(**kwargs)
        if not 'invoice_formset' in context:
            context['invoice_formset'] = formset_factory(self.invoice_form_class, extra=3, can_delete=True, formset=BaseFormSet)
        return context

There's probably an easy way to do this, but i'm not finding it anywhere

EDIT: Thanks to @mariodev, i've learned about the inline_formsetfactory, and i'm using it. Now i can fill the formsets with the existing data, and i can create and alter existing ones, but when i try to delete them, nothing happens.

So now i'm defining this formset:

InvoiceFormset = inlineformset_factory(Order, Invoice, fields=('code',), can_delete=True, extra=0)

and my view looks like:

class OrderDetailView(UpdateView):
    invoice_form_class = InvoiceForm

    def get_context_data(self, **kwargs):
        context = super(OrderDetailView, self).get_context_data(**kwargs)
        if not 'invoice_formset' in context:
            context['invoice_formset'] = InvoiceFormset(instance=self.get_object())
        return context

    def post(self, *args, **kwargs):
        data = self.request.POST
        order = self.get_object()
        form = self.form_class(data)
        invoice_formset = InvoiceFormset(data, instance=order)
        if form.is_valid() and invoice_formset.is_valid():
            self.object = form.save(order)
            for f in invoice_formset:
                f.save(self.object)
        return HttpResponseRedirect(reverse('order_detail', kwargs={'order_id': self.get_object().order_id}))

I could add some extra lines in the post() to check if i have to delete the form, but it doesn't seem right for me to do it in the view. Is there something else i'm missing?

EDIT AGAIN:

Ended up finding this link which fix exactly this last problem i was having, so now it's all good!

1

There are 1 best solutions below

1
On

I think it's better use normal function based views (FBV) for this. Understand what's going on first and then gradually move to CBV if you really need to.

This will help you with FBV:

http://catherinetenajeros.blogspot.com/2013/03/inline-formset-saving-and-updating-two.html

This may help you with CBV:

django class-based views with inline model-form or formset