Я предполагаю, что все экземпляры ArticleBase являются экземплярами подклассов ArticleBase.
Одним из решений является сохранение имени подкласса в ArticleBase и некоторых методов, которые возвращают объект подкласса или подкласса на основе этой информации. Поскольку наследование нескольких таблиц определяет свойство родительского экземпляра для доступа к дочернему экземпляру, все это довольно просто.
from django.db import models
class ArticleBase(models.Model):
title = models.CharField()
author = models.CharField()
# Store the actual class name.
class_name = models.CharField()
# Define save to make sure class_name is set.
def save(self, *args, **kwargs):
self.class_name = self.__class__.__name__
super(ArticleBase, self).save(*args, **kwargs)
# Multi-table inheritance defines an attribute to fetch the child
# from a parent instance given the lower case subclass name.
def get_child(self):
return getattr(self, self.class_name.lower())
# If indeed you really need the class.
def get_child_class(self):
return self.get_child().__class__
# Check the type against a subclass name or a subclass.
# For instance, 'if article.child_is(News):'
# or 'if article.child_is("News"):'.
def child_is(self, cls):
if isinstance(cls, basestring):
return cls.lower() == self.class_name.lower()
else:
return self.get_child_class() == cls
class Review(ArticleBase):
rating = models.IntegerField()
class News(ArticleBase):
source = models.CharField()
Это ни в коем случае не единственный способ сделать это. Это, однако, довольно простое и прямолинейное решение. Отличное приложение contrib contenttypes и универсальный модуль, который его использует, предлагают множество способов сделать это, ну, в общем.
Может быть полезно иметь следующее в ArticleBase:
def __unicode__(self)
return self.get_child().__unicode__()
В этом случае следует помнить, что неудача в определении __unicode__
в подклассах или вызов __unicode__
в экземпляре ArticleBase (который не был разделен на подклассы) приведет к бесконечной рекурсии. Таким образом, приведенное ниже предостережение о проверке работоспособности (например, предотвращение только такой реализации ArticleBase напрямую).
Отказ от ответственности:
Этот код не проверен, я уверен, что у меня есть опечатка или два, но основная концепция должна быть надежной. Код производственного уровня, вероятно, должен иметь некоторую проверку работоспособности для перехвата ошибок использования.