Django admin inline inlines (or, three model edits at once)

I have a set of models that look like this:

class Page(models.Model): title = models.CharField(max_length=255) class LinkSection(models.Model): page = models.ForeignKey(Page) title = models.CharField(max_length=255) class Link(models.Model): linksection = models.ForeignKey(LinkSection) text = models.CharField(max_length=255) url = models.URLField() 

and admin.py, which looks like this:

 class LinkInline(admin.TabularInline): model = Link class LinkSectionInline(admin.TabularInline): model = LinkSection inlines = [ LinkInline, ] class PageAdmin(admin.ModelAdmin): inlines = [ LinkSectionInline, ] 

My goal is to get an admin interface that allows me to edit everything on one page. The end result of this model is that things are generated as a + template that looks more or less similar:

 <h1>{{page.title}}</h1> {% for ls in page.linksection_set.objects.all %} <div> <h2>{{ls.title}}</h2> <ul> {% for l in ls.link_set.objects.all %} <li><a href="{{l.url}}">{{l.title}}</a></li> {% endfor %} </ul> </div> {% endfor %} 

I know that the inline-in-anline inline trick doesn't work in the Django admin, as I expected. Does anyone know how to enable such a three-level simulation? Thanks in advance.

+51
python django django-models django-admin
Mar 31 '09 at 19:20
source share
4 answers

You need to create a custom form and template for LinkSectionInline .

Something like this should work for the form:

 LinkFormset = forms.modelformset_factory(Link) class LinkSectionForm(forms.ModelForm): def __init__(self, **kwargs): super(LinkSectionForm, self).__init__(**kwargs) self.link_formset = LinkFormset(instance=self.instance, data=self.data or None, prefix=self.prefix) def is_valid(self): return (super(LinkSectionForm, self).is_valid() and self.link_formset.is_valid()) def save(self, commit=True): # Supporting commit=False is another can of worms. No use dealing # it before it needed. (YAGNI) assert commit == True res = super(LinkSectionForm, self).save(commit=commit) self.link_formset.save() return res 

(This has just gone astray and not verified, but it should make you go in the right direction.)

Your template just needs to display the form and .link_formset form accordingly.

+20
Aug 26 '09 at 5:18
source share

Django-nested-inlines is built for just that. The use is simple.

 from django.contrib import admin from nested_inlines.admin import NestedModelAdmin, NestedStackedInline, NestedTabularInline from models import A, B, C class MyNestedInline(NestedTabularInline): model = C class MyInline(NestedStackedInline): model = B inlines = [MyNestedInline,] class MyAdmin(NestedModelAdmin): pass admin.site.register(A, MyAdmin) 
+4
Sep 28 '14 at 18:02
source share

My recommendation actually is to change your model. Why not have ForeignKey in Link before LinkSection ? Or, if it is not OneToMany, perhaps the ManyToMany field? The admin interface will generate this for free. Of course, I do not recommend this if the links logically have nothing to do with the link sections, but maybe they do it? If they do not, explain what the intended organization is. (For example, 3 section links are fixed or arbitrary?)

+1
Apr 04 '09 at 14:05
source share

You can create a new class similar to TabularInline or StackedInline, which can use inline fields.

Alternatively, you can create new admin templates, especially for your model. But this, of course, overrides the excellent admin interface features.

0
Aug 25 '09 at 17:29
source share



All Articles