Django OneToOneField для нескольких моделей
Предположим, у нас есть базовая модель:
class BaseModel(models.Model):
pass
с некоторыми подклассами:
class Submodel1(BaseModel):
some_field = models.TextField()
...
class Submodel9(BaseModel):
another_field = models.TextField()
Каждая подмодель определяется в своем собственном приложении Django. Могут появляться новые приложения с новыми подмоделями.
У нас также есть другая модель, давайте назовем это RelatedModel
который должен иметь отношение один к одному BaseModel
:
class RelatedModel(models.Model):
the_thing = models.OneToOneField(BaseModel, null=True, blank=True)
Можно ли определить такое отношение, если BaseModel.Meta.abstract == True
? Или без определения BaseModel
совсем?
Я опубликовал некоторые решения в виде ответов ниже, но они кажутся мне немного безобразными.
2 ответа
Вместо того, чтобы поставить отношение к RelatedModel
, можно поставить Submodel1 .. Submodel9
,
class Submodel1(models.Model):
some_field = models.TextField()
related_model = models.OneToOneField(RelatedModel,
null=True, blank=True,
related_name='the_thing')
...
class Submodel9(models.Model):
another_field = models.TextField()
related_model = models.OneToOneField(RelatedModel,
null=True, blank=True,
related_name='the_thing')
Или, если мы сделаем BaseModel
абстрактно, мы можем определить это прямо в BaseModel
:
class BaseModel(models.Model)
related_model = models.OneToOneField(RelatedModel,
null=True, blank=True,
related_name='the_thing')
class Meta:
abstract = True
Это позволит получить доступ SubmodelX
из экземпляра RelatedModel
используя поле с именем the_thing
так же, как в примере наследования нескольких таблиц.
С помощью GenericForeignKeys можно добиться:
class RelatedModel(models.Model):
content_type_of_the_thing = models.ForeignKey(ContentType)
id_of_the_thing = models.PositiveIntegerField()
the_thing = GenericForeignKey('content_type_of_the_thing', 'id_of_the_thing')
class Meta:
unique_together = ('content_type_of_the_thing', 'id_of_the_thing')
# TODO: restrict `content_type_of_the_thing` by `Submodel1 .. Submodel9` somehow
# Take into account that new submodels can appear