【问题标题】:through model for an Abstract model通过抽象模型的模型
【发布时间】:2015-08-10 22:05:57
【问题描述】:

我有一个抽象模型:

class Distributor(models.Model):

    class Meta:
        abstract = True

和 2 个继承它的模型:

class DistributorGroup(Distributor):
    pass

class DistributorPerson(Distributor):
    pass

我还有一个链接模型:

class Link(models.Model):
    distributors_persons = models.ManyToManyField(
        'people.DistributorPerson', blank=True, related_name='distributors_persons_of_links')
    distributors_groups = models.ManyToManyField(
        'groups.DistributorGroup', blank=True, related_name='distributors_groups_of_links')

链接可以与其中一个分销商有关系。我通过添加 2 m2m 并将 blank=True 设置为两者来完成此行为。

现在我意识到我需要一个through 模型来连接Distributors 和Link。但是由于through 模型不能将抽象模型作为外键,所以我不知道该怎么做。我是否需要为 DistributorPersonDistributorGroup 创建 2 个单独的 through 模型,或者有一种方法可以使用 1 个 through 模型完成此操作。另外我不知道我在Link 模型中的 2 m2m 是否是完成我想要的行为的正确方法。

所以我想知道用抽象模型组织这些 m2m 模型的方法是什么。

【问题讨论】:

    标签: python django django-models django-orm


    【解决方案1】:

    第一个问题是DistributorPersonDistributorGroup 是否真的需要单独的表。如果它们非常相似,那么只使用一个表可能是有意义的。 (例如,如果您对电话号码进行建模,您可能不会使用单独的 Home、Work 和 Mobile 表,而是使用带有类型字段的单个表。)

    (请注意,您可以使用proxy models 来允许不同的Django 模型共享同一个数据库表。)

    如果您确实需要单独的表格,那么您可以查看GenericForeignKey。这是一种允许外键引用来自不同模型类型的对象的机制。在您的情况下,这可能看起来像:

    class DistributorGroup(Distributor):
        distributor_links = GenericRelation(DistributorLink, related_query_name="distributor_groups")
    
    class DistributorPerson(Distributor):
        distributor_links = GenericRelation(DistributorLink, related_query_name="distributor_persons")
    
    class Link(models.Model):
        pass
    
    class DistributorLink(models.Model):
        link = models.ForeignKey(Link);
    
        content_type = models.ForeignKey(ContentType)
        object_id = models.PositiveIntegerField()
        content_object = GenericForeignKey('content_type', 'object_id')
    

    有关示例和更多详细信息,请参阅generic relations 上的文档。

    最后,如果一切都失败了,您确实可以为这两种关系创建两个单独的 M2M 表。

    请注意,这些都与抽象模型无关。抽象模型只是 Django 中代码重用的一种机制,它们不会影响您在它们上运行的表或查询。

    【讨论】:

    • 感谢您的回答!你已经回答了我的一个问题,所以我现在对另一个感兴趣。我不能为两个分销商提供一个表,因为它们的功能和字段都大不相同,但感谢您展示设计数据库的其他方法。另一个问题是关于through 模型。如果我使用 2 个 m2m 模型,我是否需要为每个模型创建一个 through 模型(它们绝对相同)?
    • @pythad:是的,但是您认为需要两个 M2M 表有什么原因吗? (我知道您需要两个分发器表。)请注意,上面的DistributorLink 自定义 M2M 表,它只是没有在 Link 上声明,因为 Django 不提供该选项与泛型关系。将a_link.distributor_persons.all()(您的旧方式)与DistributorPerson.objects.filter(distributor_links=a_link)(这种方式)进行比较。
    • 我读过一些关于这些泛型关系的文章,我对它们的看法有点不同,现在我明白你在说什么了。使用您的代码,实现through 模型的方式与普通模型相同吗?
    • @pythad:我不确定我是否理解你的问题。 DistributorLink 直通模型,您这样做而不是Link上声明ManyToManyField。不过效果是一样的。请记住,ManyToManyField 不是一个真正的字段,它只是为执行查询创建了一些语法糖。如果没有它,查询可能会更冗长(请参阅我上一条评论中的示例),但其他事情会比您有两个 M2M 表更容易(例如,计算与链接关联的所有分销商)。
    • 哦,好吧,现在我明白这是如何工作的了。明天我将尝试实施。谢谢你的帮助,你让我明白了很多事情!
    猜你喜欢
    • 2016-01-10
    • 2012-02-15
    • 1970-01-01
    • 2013-10-21
    • 2020-08-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-06-16
    相关资源
    最近更新 更多