Nested inlines in the Django admin?

Viewed 28765

Alright, I have a fairly simple design.

class Update(models.Model):
    pub_date = models.DateField()
    title = models.CharField(max_length=512)

class Post(models.Model):
    update = models.ForeignKey(Update)
    body = models.TextField()
    order = models.PositiveIntegerField(blank=True)

class Media(models.Model):
    post = models.ForeignKey(Post)
    thumb = models.ImageField(upload_to='frontpage')
    fullImagePath = models.ImageField(upload_to='frontpage')

Is there an easy-ish way to allow a user to create an update all on one page?

What I want is for a user to be able to go to the admin interface, add a new Update, and then while editing an Update add one or more Posts, with each Post having one or more Media items. In addition, I want the user to be able to reorder Posts within an update.

My current attempt has the following in admin.py:

class MediaInline(admin.StackedInline):
    model = Media

class PostAdmin(admin.ModelAdmin):
    inlines = [MediaInline,]

This let's the user add a new Post item, select the relevant Update, add the Media items to it, and hit save - which is fine. But there's no way to see all the Posts that belong to a given Update in a single place, which in turn means you can't roderder Posts within an update. It's really quite confusing for the end user.

Help?

6 Answers

Use django-nested-admin which is the best package to do nested inlines.

First, install "django-nested-admin":

pip install django-nested-admin

Then, add "nested_admin" to "INSTALLED_APPS" in "settings.py":

# "settings.py"

INSTALLED_APPS = (
    # ...
    "nested_admin", # Here
)

Then, add "path('_nested_ad..." to "urlpatterns" in "urls.py":

# "urls.py"

from django.urls import include, path

urlpatterns = [
    # ...
    path('_nested_admin/', include('nested_admin.urls')), # Here
]

Finally, extend "NestedTabularInline" with "MediaInline()" and "PostInline()" classes and extend "NestedModelAdmin" with "UpdateAdmin()" class in "admin.py" as shown below:

# "admin.py"

from .models import Media, Post, Update
from nested_admin import NestedTabularInline, NestedModelAdmin

class MediaInline(NestedTabularInline):
    model = Media

class PostInline(NestedTabularInline):
    model = Post
    inlines = [MediaInline]

@admin.register(Update)
class UpdateAdmin(NestedModelAdmin):
    inlines = [PostInline]
Related