Add InlineModelAdmin to a django.contrib app

Entry posted by Jason on August 4, 2008 in the Django category.

I recently upgraded to Django 1.0 alpha. This meant that I must make a couple of code adjustments while working through examples in Practical Django Projects. While i've already created the blog example in the book, I am now working backwards and starting the simple cms example. Of course there are a couple of obvious and very easy adjustments to make in order to get the admin interface working.

If you are working on Django 1.0, make sure your urls.py file looks like the below example instead of what's in the book.

1
2
3
4
5
6
from django.contrib import admin
admin.autodiscover()

urlpatterns = patterns('',
    (r'^admin/(.*)', admin.site.root),
)

That was the easy part for me. Then a new problem arose when I started working on the SearchKeyword application in the book. The example in the books shows the following completed SearchKeyword model.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
class SearchKeyword(models.Model):
    keyword = models.CharField(maxlength=50, core=True)
    page = models.ForeignKey(FlatPage, edit_inline=models.STACKED,
    min_num_in_admin=3, num_extra_on_change=1)

    class Admin:
        pass

    def __unicode__(self):
        return self.keyword

This will not work in Django 1.0 for several reasons. First off, you cannot define admin in the class itself. It must go into it's own ModelAdmin function located in a new file called admin.py. It must also be registered with the admin interface. The completed admin.py and models.py files are below. Add django.contrib.admin to your installed apps before trying the below code.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
# models.py

from django.db import models
from django.contrib.flatpages.models import FlatPage

class SearchKeyword(models.Model):
    keyword = models.CharField(max_length=50, core=True)
    page = models.ForeignKey(FlatPage)

    def __unicode__(self):
        return self.keyword
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
# admin.py

from django.contrib import admin
from cms.search.models import SearchKeyword
from django.contrib.flatpages.models import FlatPage
from django.utils.translation import ugettext_lazy as _

class SearchKeywordInline(admin.StackedInline):
    model = SearchKeyword
    extra = 3
    max_num = 6

class FlatPageAdmin(admin.ModelAdmin):
    fieldsets = (
        (None, {'fields': ('url', 'title', 'content', 'sites')}),
        (_('Advanced options'), {'classes': ('collapse',), 'fields': ('enable_comments', 'registration_required', 'template_name')}),
    )
    list_display = ('url', 'title')
    list_filter = ('sites', 'enable_comments', 'registration_required')
    search_fields = ('url', 'title')
    inlines = [SearchKeywordInline,]

admin.site.unregister(FlatPage)
admin.site.register(FlatPage, FlatPageAdmin)

The above admin.py file will make it so the SearchKeyword model is accessible in the FlatPages admin interface. It does this by first creating the SearchKeywordInline class and adding it to a new FlatPage ModelAdmin function. I also didn't want to loose out on any of the extra options from the default django.contrib.flatpages ModelAdmin so I copied lines 6 and 14-20 from it and added the code to my file. Line 23 then unregisters the default FlatPage ModelAdmin and line 24 registers this new one with my inlines included. Another example of something like this can be accomplished with the django.contrib.auth Users model and a UserProfile model you create.


Comments:

gravatarOn September 5, 2008
Jason Broyles said:

Recently moved my blog over and didn't take any of the comments. Thought I would repost this one from Tim Huegdon. He has expanded on this post and made it better.

http://nefariousdesigns.co.uk/archive/2008/09/practical-django-projects-and-django-10/


Posting of new comments has been disabled.


A Django site.