Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do you save the order of a django inline formset?

In Django, I'm using an inlineformset with can_order = True, on a model that has order_with_respect_to set. I've set up drag and drop on the front end, which results in Django's autogenerated ORDER form fields (which I've hidden) changing to reflect the new order. I've verified I'm POSTing the new order correctly to the server, but Django seems to ignore it, and saves the models in the original order. The automatically-created _order fields in the database never change.

How can I get Django to save the models using order specified in the formset? Do I need to do anything special other than calling save() on the formset?

like image 880
LS55321 Avatar asked Jul 22 '11 21:07

LS55321


People also ask

What is inline formset in Django?

Django formset allows you to edit a collection of the same forms on the same page. It basically allows you to bulk edit a collection of objects at the same time.

What is Formset factory in Django?

Django model formsets provide a way to edit or create multiple model instances within a single form. Model Formsets are created by a factory method. The default factory method is modelformset_factory(). It wraps formset factory to model forms. We can also create inlineformset_factory() to edit related objects.


2 Answers

Evan Borgstrom proposed solution does not work together with can_delete=True.

Here is my solution that also works with can_delete=True:

for instance in formset.save(commit=False):
    # ... do something with m2m relationships ...
for form in formset.ordered_forms:
    form.instance.order = form.cleaned_data['ORDER']
    form.instance.save()
like image 134
sirex Avatar answered Oct 07 '22 01:10

sirex


I had the same problem and after digging through the Django source figured that it's something you need to do on your own.

My original implementation looked something like this:

services = service_formset.save(commit=False)
for service in services:
    # ... do something with m2m relationships ...
    service.save()

However, as you've found this doesn't set the ORDER. So instead my implementation now looks like:

for form in service_formset:
    service = form.save(commit=False)
    # ... do something with m2m relationships ...
    service.order_order = form.cleaned_data['ORDER']
    service.save()

In my example above 'order_order' is the field I'm using to track order on my models.

Also remember that you need to specify the 'ordering' attribute of your model's Meta class to ensure that when you generate the formset again the elements are in the correct order.

class Service(models.Model):
    # ...
    order_order = models.IntegerField(default=0)
    class Meta:
        ordering = ['order_order',]
like image 32
Evan Borgstrom Avatar answered Oct 07 '22 00:10

Evan Borgstrom