Django Admin nested inline

tuna picture tuna · Jan 13, 2013 · Viewed 37.6k times · Source

I need a nested django admin inline, which I can include the date field inlines in an other inline like below.

I have the models below:

class Person(models.Model):
     name = models.CharField(max_length=200)
     id_no = models.IntegerField()

class Certificate(models.Model):
     cerfificate_no = models.CharField(max_length=200)
     certificate_date = models.DateField(max_length=100)
     person = models.ForeignKey(Person)
     training = models.CharField(max_length=200)

class Training_Date(models.Model):
      date = models.DateField()
      certificate = models.ForeignKey(Certificate)

and the admin below:

class CertificateInline(admin.StackedInline):
    model = Certificate

class PersonAdmin(admin.ModelAdmin):
     inlines = [CertificateInline,]
admin.site.register(Person,PersonAdmin)

but i need to include the Training_Date model as inline which is part of Certificate admin inline.

Any idea ?

Answer

Danny W. Adair picture Danny W. Adair · Jan 15, 2013

There has been some movement in https://code.djangoproject.com/ticket/9025 recently, but I wouldn't hold my breath.

One common way around this is to link to an admin between first and second (or second and third) level by having both a ModelAdmin and an Inline for the same model:

Give Certificate a ModelAdmin with TrainingDate as an inline. Give CertificateInline an additional field "Details" which is a link to its ModelAdmin change form.

models.py:

from django.core import urlresolvers

class Certificate(models.Model):

    # ...

    def changeform_link(self):
        if self.id:
            # Replace "myapp" with the name of the app containing
            # your Certificate model:
            changeform_url = urlresolvers.reverse(
                'admin:myapp_certificate_change', args=(self.id,)
            )
            return u'<a href="%s" target="_blank">Details</a>' % changeform_url
        return u''
    changeform_link.allow_tags = True
    changeform_link.short_description = ''   # omit column header

admin.py:

# Certificate change form has training dates as inline

class TrainingDateInline(admin.StackedInline):
    model = TrainingDate

class CertificateAdmin(admin.ModelAdmin):
    inlines = [TrainingDateInline,]
admin.site.register(Certificate ,CertificateAdmin)

# Person has Certificates inline but rather
# than nesting inlines (not possible), shows a link to
# its own ModelAdmin's change form, for accessing TrainingDates:

class CertificateLinkInline(admin.TabularInline):
    model = Certificate
    # Whichever fields you want: (I usually use only a couple
    # needed to identify the entry)
    fields = ('cerfificate_no', 'certificate_date', 'changeform_link')
    readonly_fields = ('changeform_link', )

class PersonAdmin(admin.ModelAdmin):
    inlines = [CertificateLinkInline,]
admin.site.register(Person, PersonAdmin)