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 ответа

/questions/17495297/dolzhen-li-ya-kakim-libo-obrazom-izbegat-mnogotablichnogo-konkretnogo-nasledovaniya-v-django/17495314#17495314

Вместо того, чтобы поставить отношение к 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
Другие вопросы по тегам