【问题标题】:django - What are the alternatives to having a ForeignKey to an abstract class?django - 将 ForeignKey 用于抽象类的替代方法是什么?
【发布时间】:2023-04-05 14:19:01
【问题描述】:

我想在 Django 中有一个抽象的Company 模型,并根据所涉及的公司类型对其进行扩展:

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')

但这给出了可怕的错误:

main.Profile.company: (fields.E300) 字段定义与 模型 'Company',要么未安装,要么是抽象的。

所以我想我正在尝试做的事情无法完成。我看到contenttypes 框架可以用于此目的,正如this 问题中所回答的那样。我的问题是我不希望 company 字段指向 any 模型,而只是 Company 模型的子类。

还有什么我可以用来做这个的吗?

【问题讨论】:

    标签: python django django-models


    【解决方案1】:

    ForeignKey 不能直接引用抽象模型的原因是从抽象模型继承的各个模型实际上在数据库中都有自己的表。

    外键只是引用相关表中 id 的整数,因此如果外键与抽象模型相关,则会产生歧义。例如,可能有一个 BuyerSeller 实例,每个实例的 id 为 1,而管理器不知道要加载哪个实例。

    使用generic relation 可以通过记住您在关系中谈论的模型来解决此问题。

    它不需要任何额外的模型,它只是使用一个额外的列。

    例子-

    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>
    

    【讨论】:

    • 感谢您的回答!在您的示例中,company 可以引用 any 模型,对吗?例如,我也可以让它指向 User 模型?我宁愿在某个地方指定它应该只指向 Company 的子类,这样 Django 就不会让我引用用户。但我想这可以作为验证步骤来完成?
    • 当然,请查看this answer。基本上你将limit_choices_to 参数传递给ForeignKey
    猜你喜欢
    • 2010-12-25
    • 1970-01-01
    • 2012-11-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多