Django polymorphism hack
I'm trying to bake out a sort of "single table inheritence" a.k.a. "table per hierarchy" model in Django.
Here's what I'd like to do:
class PolymorphicModel(models.Model):
content_type = models.ForeignKey(ContentType)
class Meta:
abstract = True
def __init__(self, *args, **kwargs):
super(PolymorphicModel, self).__init__(*args, **kwargs)
# Dynamically switch the class to the actual one
self.__class__ = self.content_type.model_class()
def save(self, *args, **kwargs):
if not self.content_type:
# Save the actual class name for the future.
self.content_type = ContentType.objects.get_for_model(self.__class__)
super(PolymorphicModel, self).save(*args, **kwargs)
And then the actual hierarchy:
class Base(PolymorphicModel):
a = models.IntegerField()
b = models.IntegerField()
@abstractmethod
def som开发者_开发技巧ething(self): pass
class DerivedA(Base):
def something(self):
return self.a
class DerivedB(Base):
def something(self):
return self.b
Unfortunately I get an error DoesNotExist
when constructing DerivedA()
. It complains about content_type
not existing.
EDIT:
Concerning my questions:
- Why do I get the exception, how to fix it?
See my answer below: content_type
is apparently not a viable name.
- Is the thing that I'm trying to achieve doable this way?
Yes it is! And it works beautifully. Using class names instead of content type is also possible. This has an added value of handling proxy = True
appropriately.
Ups, well apparently content_type
is a reserved name. I changed the property name to ct
and it works now.
I've published by solution here: http://djangosnippets.org/snippets/2408/
精彩评论