AndrewIngram / django-extra-views

Django's class-based generic views are awesome, let's have more of them.
MIT License
1.39k stars 172 forks source link

UpdateWithInlinesView Inline Form Ordering #240

Closed Maximost closed 2 years ago

Maximost commented 2 years ago

Good day,

I'm not sure if I'm missing something specific in the documentation but I am not able to get inline forms to output to the template with the ordering specified in the model meta. I also could not find a way to change the order_by in the query executed by the InlineFormSetFactory view. No matter what I have tried, inline forms are always rendered in table order (by id).

Model meta ordering is honored in my list and detail views (just not on UpdateWithInlinesView). Am I doing something wrong or is this functioning as designed?

The model in question: class Tasks(models.Model): class Meta: verbose_name = "project task" verbose_name_plural = "project tasks" ordering = ['task_order', 'task_due'] project = models.ForeignKey(Project, on_delete=models.CASCADE) task_order = models.IntegerField('order', blank=True, null=True) user = models.ForeignKey(User, on_delete=models.SET_NULL, null=True, blank=True) task_type = models.ForeignKey(TaskTypes, on_delete=models.SET_NULL, null=True, blank=False) task_start = models.DateField('due', blank=True, null=True) task_due = models.DateField('due', blank=True, null=True) is_started = models.BooleanField('started', default=False) is_complete = models.BooleanField('done', default=False) task_effort = models.DecimalField('est', max_digits=12, decimal_places=2, default=0) task_note = models.CharField('details', max_length=400, blank=True) def __str__(self): return str(self.user) + ' ' + str(self.task_type) + ' ' + str(self.task_due) + ' ' + str(self.task_effort)

The inline view: class task_edit_inline(InlineFormSetFactory): form_class = taskEditForm model = Tasks factory_kwargs = {'extra': 0, 'max_num': None, 'can_order': False, 'can_delete': True}

The UpdateWithInlinesView: class task_grid_edit_view(SuccessMessageMixin, UpdateWithInlinesView): model = Project template_name = 'otis/edit_task_grid.html' form_class = TaskGridForm inlines = [task_edit_inline] success_message = "Tasks updated" def get_context_data(self, **kwargs): context = super(task_grid_edit_view, self).get_context_data(**kwargs) return context

Thank you so much for any insight you might have!

sdolemelipone commented 2 years ago

Hi. I'm not sure about Django's ordering for related managers, I thought that they would return results using the ordering in the meta. Does the below work for explicit ordering?

class task_edit_inline(InlineFormSetFactory):
    ...
    def get_formset_kwargs(self):
        kwargs = super().get_formset_kwargs()
        kwargs["queryset"] = self.object.task_set.order_by("task_order", "task_due")
        return kwargs
Maximost commented 2 years ago

I owe you a debt of gratitude! Your suggestion worked perfectly!

It is strange that the model ordering is not honored. Honestly, after banging my head for several hours on this over the weekend, I was resigned to imposing a list sort using Javascript...not an elegant solution.

sdolemelipone commented 2 years ago

Great, I'm glad it worked for you! :-) I'm pretty sure my formsets do respect the Meta so that is odd.