django - каковы альтернативы использованию иностранного ключа для абстрактного класса?


Я хочу иметь абстрактную Company модель в Django и расширять ее в зависимости от типа вовлеченной компании:

class Company(models.Model):
    name = models.CharField(max_length=100)
    address = models.CharField(max_length=100)

    class Meta:
        abstract = True

class Buyer(Company):
    # Buyer fields..
    pass

class Seller(Company):
    # Seller fields...
    pass
Каждый пользователь в системе связан с компанией, поэтому я хочу добавить следующее в профиль пользователя:
company = models.ForeignKey('Company')

Но это дает страшную ошибку:

Главная.Профиль.компания: (поля.E300) поле определяет отношение с модель 'компания', которая либо не установлена, либо является абстрактной.

Итак, я представляю, что я пытаюсь сделать. сделать ничего нельзя. Я увидел, что для этой цели может быть использована структураcontenttypes , как ответ на этот вопрос. Моя проблема с этим заключается в том, что я не хочу, чтобы поле company указывало на любую модель, а только подклассы модели Company.

Есть ли что-нибудь еще, что я могу использовать для этой цели?
1 2

1 ответ:

Причина, по которой ForeignKey не может ссылаться непосредственно на абстрактную модель, заключается в том, что отдельные модели, наследуемые от абстрактной модели, фактически имеют свои собственные таблицы в базе данных.

Внешние ключи-это просто целые числа, ссылающиеся на идентификатор из связанной таблицы, поэтому неоднозначность будет создана, если внешний ключ связан с абстрактной моделью. Например, может быть экземпляр Buyer и Seller с идентификатором 1, и менеджер не будет знать, какой из них загружать.

Используя a родовое отношение решает эту проблему, также вспоминая, о какой модели вы говорите в отношении.

Он не требует никаких дополнительных моделей, он просто использует один дополнительный столбец.

Пример -

from django.contrib.contenttypes.models import ContentType
from django.contrib.contenttypes.fields import GenericForeignKey

class Foo(models.Model):
  company_type = models.ForeignKey(ContentType)
  company_id = models.PositiveIntegerField()
  company = GenericForeignKey('company_type', 'company_id')

А затем -

>>> seller = Seller.objects.create()
>>> buyer = Buyer.objects.create()
>>> 
>>> foo1 = Foo.objects.create(company = seller) 
>>> foo2 = Foo.objects.create(company = buyer) 
>>> 
>>> foo1.company 
<Seller: Seller object>
>>> foo2.company 
<Buyer: Buyer object>