'Django ModelAdmin Fieldset within fieldset

What I've been asked create is an admin page with the following layout:

  • Fieldset 1 name

    • Section 1 name
      • field 1
      • field 2
  • Fieldset 2 name

    • Section 2 name
      • field 3

and so on.

I can create the fieldsets with ModelAdmin.fieldsets obviously, but its the inner grouping or "Sections" that I'm having difficulty with. The fields to display all belong to the same model, so I can't achieve this with Inlines (or at least I believe I can't).

I'm pretty sure the only way to achieve what I want is to create a custom template and to by pass Django's default loveliness but I'd ideally like to extend the Django Admin because this Fieldset -> Section -> fields layout will be required for several models and I don't want to have to manually generate forms & templates for each model, if I can help it.

Could anyone point me in the right direction to achieve the above layout?

Thanks



Solution 1:[1]

Unfortunately you're out of luck, the Django admin does not support nested fieldsets and has no way to output other structural tags, except by customising the templates.

You can have a look at:
http://django-betterforms.readthedocs.org/en/latest/basics.html

It supports nested fieldsets, so this code will help you when you are customising your admin templates.

Solution 2:[2]

If you are trying to create a page something like this :

enter image description here

Then you can add following to your admin file :

from django.contrib import admin

class FlatPageAdmin(admin.ModelAdmin):
    fieldsets = (
        (None, {
            'fields': ('url', 'title', 'content', 'sites')
        }),
        ('Advanced options', {
            'classes': ('collapse',),
            'fields': ('registration_required', 'template_name'),
        }),
    )

And for more details you can check this page

Solution 3:[3]

It looks like Django still doesn't support nested fieldsets (April 2022).

Instead, I had to go through and organize my fieldsets into tuples

('Water Conveyance', {
    'classes': ('collapse',),
    'fields': (('spillway_gate', 'bypass_valve'), ('trash_exclusion', 'intake_gate', 'intake_passage', 'shutoff_valve'), ('cone', 'isolation'))
}),

And then set verbose_name on all my field definitions

spillway_gate = models.CharField(max_length=25, choices=Key.choices, default=Key.default, verbose_name="Bypass - Spillway Gate")
bypass_valve = models.CharField(max_length=25, choices=Key.choices, default=Key.default, verbose_name="Bypass - Bypass Valve")

Not as pretty, but it works

Screenshot

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Anentropic
Solution 2
Solution 3 Tyler2P