13

我认为我需要创建一个“多对多通用关系”。

我有两种类型的参与者:

class MemberParticipant(AbstractParticipant):
    class Meta:
        app_label = 'participants'


class FriendParticipant(AbstractParticipant):
    """
    Abstract participant common information shared for all rewards.
    """
    pass

这些参与者可以有 2 种不同类型的 1 个或多个奖励(奖励模型来自另一个应用程序):

class SingleVoucherReward(AbstractReward):
    """
    Single-use coupons are coupon codes that can only be used once
    """
    pass

class MultiVoucherReward(AbstractReward):
    """
    A multi-use coupon code is a coupon code that can be used unlimited times.
    """

所以现在我需要把这些都联系起来。这就是我想建立这种关系的方式(见下文)这是否可行,你看到任何问题吗?

建议的链接模型如下:

class ParticipantReward(models.Model):


    participant_content_type = models.ForeignKey(ContentType, editable=False,
                                                        related_name='%(app_label)s_%(class)s_as_participant',
                                                        )
    participant_object_id = models.PositiveIntegerField()
    participant = generic.GenericForeignKey('participant_content_type', 'participant_object_id')


    reward_content_type = models.ForeignKey(ContentType, editable=False,
                                                        related_name='%(app_label)s_%(class)s_as_reward',
                                                        )
    reward_object_id = models.PositiveIntegerField()
    reward = generic.GenericForeignKey('reward_content_type', 'reward_object_id')

注意:我使用的是 Django 1.6

4

2 回答 2

16

鉴于您现有的表格,您的方法正是正确的方法。虽然没有任何官方消息(这个讨论,涉及 2007 年的核心开发人员,似乎没有去任何地方),我确实找到了这篇博客文章,它采用了相同的方法(并在第三方库中提供),还有一个这里的流行答案是相似的,除了关系的一侧是通用的。

我想说这个功能从未进入 django 的主干的原因是,虽然它是一个罕见的需求,但使用现有工具很容易实现。此外,想要自定义“通过”表的机会可能非常高,因此大多数最终用户实现无论如何都会涉及一些自定义代码。

唯一可能更简单的方法是拥有基本的参与者和奖励模型,它们之间具有多对多关系,然后使用多表继承将这些模型扩展为会员/朋友等。

最终,您只需要权衡通用关系的复杂性与将对象数据分布在两个模型中的复杂性。

于 2013-11-06T20:26:52.397 回答
9

回复晚了,但是我在寻找一种实现通用 m2m 关系的方法时发现了这个对话,并且觉得我的 2 美分对未来的谷歌员工会有帮助。

正如格雷格所说,您选择的方法是一种很好的方法。

但是,当您想要使用反向关系或预取等功能时,我不会将通用多对多定义为“易于使用现有工具实现”。

第 3 方应用程序 django-genericm2m 很好,但在我看来有几个缺点(事实上,“通过”对象默认都在同一个数据库表中,并且您没有“添加”/“删除”方法 -因此批量添加/删除)。

考虑到这一点,因为我需要一些东西来实现通用的多对多关系“django 方式”,而且因为我想了解一些关于 django 内部结构的知识,所以我最近发布了django-gm2m。它具有与 django 的内置 GenericForeignKey 和 ManyToManyField 非常相似的 API(具有预取,通过模型......)并添加了删除行为自定义。它目前唯一缺少的是合适的 django 管理界面。

于 2014-10-08T21:54:27.150 回答