thoughtherder

type polymorphism in django

Monday, May 24, 2010 6:15 p.m.

models.py


from django.db import models
from django.contrib.contenttypes.models import ContentType
from django.contrib.contenttypes import generic


related_object_limits = {'model__in': ('specificitem1', \
    'specificitem2')}

class RelatedItem(models.Model):

    content_type = models.ForeignKey(ContentType, \
        related_name='main_object', \ 
        limit_choices_to=related_object_limits)
    object_id = models.PositiveIntegerField()
    content_object = \
        generic.GenericForeignKey('content_type', \
        'object_id')

    related_content_type = \
        models.ForeignKey(ContentType, \
        related_name='related_object', \
        limit_choices_to=related_object_limits)
    related_object_id = models.PositiveIntegerField()
    related_object = \
        generic.GenericForeignKey('related_content_type', \
        'related_object_id')


class Item(models.Model):

    name = models.CharField(max_length=100)
    slug = models.SlugField(unique=True)
    related = generic.GenericRelation(RelatedItem, \
        content_type_field='content_type', \
        object_id_field='object_id')

    def __unicode__(self):
        return self.name

    class Meta:
        abstract = True


class SpecificItem1(Item):

    property1 = models.CharField(max_length=100)


class SpecificItem2(Item):

    property2 = models.CharField(max_length=100)

admin.py


from django.contrib import admin
from django.contrib.contenttypes.generic import GenericTabularInline

from models import SpecificItem1


class RelatedItemInline(GenericTabularInline):
    model = RelatedItem

class SpecificItem1Admin(admin.ModelAdmin):
    list_display = ('name', 'slug')
    search_fields = ('name',)
    inlines = [RelatedItemInline,]

admin.site.register(SpecificItem1, SpecificItem1Admin)

Some ideas on how to get the admin playing nice.