Practical Django Projects and Django 1.0

25th September, 2008 @ 10:41am UTC

Books, Development, Django, Python, Web / 4 Comments

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 http://www.djangobook.com/ and http://docs.djangoproject.com/en/dev/).

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 model.py and admin.py files were as follows:

# models.py

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
# 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)

Jason followed these examples with the following explanation:

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.

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

# admin.py

from django.contrib import admin
from cms.search.models 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]

admin.site.unregister(FlatPage)
admin.site.register(FlatPage, 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.

Like this post? Digg it or Del.icio.us it!

Comments (4)

Skip to the comment form…

  1. Gravatar Image Jason Broyles September 26, 2008 @ 6:44 am

    I was reading my Python feed of Reddit and about to go to sleep when I read this post. It is nice to see that posting what you do can help others.

    I too had problems figuring out what to do in this case. So once I figured it out, I decided to post it. I agree with you that developer blogs are a great resource. Thanks for the mention and I am glad I could be of some help. I like what you did here and will have to try it out myself.

    I built my blog from the example in the book. If you intend to build the blog and put it into production use, I would suggest using recaptcha for the comment moderation. I have started to get tons of comment spam lately. I am going to implement recaptcha this weekend myself. Though the book does suggest to not make comments live if it has passed 30 days. But you still have to fight off all of the comments even though they aren’t posted publicly. Also, I don’t think the book mentions anything about hiding the comment box after the 30 day mark which I still have to implement.

    Again, great article and thanks for the mentions. If you have any other problems you run across, let me know.

  2. Gravatar Image Rico Chen October 12, 2008 @ 3:13 am

    Great post. It saves me a lot of time to get the messy flat_page/searchkeyword thing working. Thanks again.

  3. Gravatar Image raja October 23, 2008 @ 3:52 pm

    Great Post. Found it right when I had the same problem.

    Little typo: When you mention Jason’s models.py for SearchKeyword, you also have the core=True. That argument is not supported in 1.0, so it would just be:

    keyword = models.CharField(max_length=50)
  4. Gravatar Image Tim October 24, 2008 @ 11:06 am

    @raja: Well spotted. Thanks for the heads up; I’ve updated the post now. :)

Leave a comment





Categories

Syndication

Technorati

© 2010 Tim Huegdon, All Rights Reserved / Website design and development by Nefarious Designs

Powered by Wordpress / Log in

Not suitable for children over the age of 6.