Practical Django Projects and Django 1.0

Posted Thursday 25th September, 2008

I recently purchased a copy of ”Practical Django Projects”, by James Bennett, with the intention of diving straight in and learning Django. I’d prepared for this daring feat of code-ninjutsu [yes, that’s the correct spelling] with a crash course in Python via ”Dive Into Python”, by Mark Pilgrim.

This appears to have been the correct choice, as I’ve already acquired a confident grasp of the concepts and techniques of Django in less than a few days of playing with it (granted; with the odd reference look-up on and

However, last night it all went a bit wrong when I upgraded my local version of Django from 0.96 to 1.0…

Most of my issues were due to the fact that some of the code in the examples, included in Practical Django Projects, was now out of date. However, I had expected this (thanks to warnings from Cyril Doussin and Steve Webster) and went about fixing the problems using the informative Porting Guide on the Django documentation site.

Following my extensive fixes, I was still experiencing issues when decoupling the Admin class from its relevant model. In most cases, this was a relatively easy process, but in one particular situation, where I had used edit_inline and needed to update the method to use the new InlineModelAdmin objects, I had a slightly confusing issue: I needed to add the InlineModelAdmin object to one of the django.contrib applications — FlatPage — to get the SearchKeyword application to work.

After a short period googling, I found an interesting, well-written blog post by Jason Broyles, ”Add InlineModelAdmin to a django.contrib app”. Unsurprisingly, it seemed others had had exactly the same issue.

Jason’s final and files were as follows:


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

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

    def __unicode__(self):
        return self.keyword

from django.contrib import admin
from 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,], FlatPageAdmin)

Jason followed these examples with the following explanation:

The above 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.

This solution fixed my problems, however I was concerned that copying and pasting code from django.contrib.flatpages ModelAdmin to was a massively inelegant solution. With that in mind, I came up with the following solution using inheritance:


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

class SearchKeyword_Inline(admin.TabularInline):
    model = SearchKeyword
    extra = 3
    max_num = 6

class FlatPageAdmin(FlatPageAdmin): 
    inlines = [SearchKeyword_Inline], FlatPageAdmin)

This worked perfectly.

As a final note, I’d just like to thank Jason for posting his solution; without that much needed information, I probably would have spent a lot more time trying to fix the issue than was really required. It just goes to show that developers that blog are a huge benefit to confused developers everywhere.

Included in: Books, Development, Django, Python, Web


  1. Accessibility
  2. Agile
  3. Ajax
  4. Apache
  5. API
  6. Architecture
  7. Books
  8. Browsers
  9. CMS
  10. CouchDB
  11. CSS
  12. Design
  13. Development
  14. Django
  15. Email
  16. Events
  17. Gaming
  18. Grammar
  19. Hardware
  20. HTML
  21. HTTP
  22. Humour
  23. Idea
  24. Information Architecture
  25. JavaScript
  26. jQuery
  27. Lean
  28. Life
  29. Linux
  30. Literature
  31. Mac OS X
  32. Management
  33. Meme
  34. Microformats
  35. Monday
  36. MySQL
  37. Networking
  38. News
  39. Personal
  40. Photoshop
  41. PHP
  42. Process
  43. Python
  44. Reference
  45. REST
  46. Science
  47. SEO
  48. Server
  49. Site
  50. Sitepimp
  51. Social
  52. Spelling
  53. Syndication
  54. Testing
  55. The Future
  56. Thoughts
  57. Tools
  58. Tutorial
  59. Tutorials
  60. Typography
  61. UI
  62. UNIX
  63. Virtualisation
  64. Web
  65. Web Standards
  66. Widgets
  67. Wii
  68. Writing
  69. Xbox
  70. XHTML