Django多对多的通用关系

Gra*_*ntU 12 python django django-models

我想我需要创建一个"多对多的通用关系".

我有两种类型的参与者:

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


class FriendParticipant(AbstractParticipant):
    """
    Abstract participant common information shared for all rewards.
    """
    pass
Run Code Online (Sandbox Code Playgroud)

这些参与者可以获得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.
    """
Run Code Online (Sandbox Code Playgroud)

所以现在我需要将这些全部联系起来.这就是我想要创建关系(见下文)的方法,你看到的任何问题?

建议的链接模型如下:

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')
Run Code Online (Sandbox Code Playgroud)

注意:我正在使用Django 1.6

Gre*_*reg 15

根据现有表格,您的方法是正确的方法.虽然没有任何官方(这个讨论,涉及2007年的核心开发人员,似乎没有去过任何地方),我确实发现这篇博文采用相同的方法(并在第三方库中提供),并且还有一个这里流行的答案是相似的,只是关系的一方是通用的.

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

唯一其他可能更简单的方法是使用基本参与者和奖励模型,并在这些模型之间使用ManyToMany关系,然后使用多表继承将这些模型扩展为成员/朋友等.

最后,您只需要权衡一般关系的复杂性与将对象的数据分布在两个模型中的复杂性.


ouk*_*ouk 9

迟到的回复,但我在寻找实现通用m2m关系的方法时发现了这个对话,并觉得我的2美分对未来的googlers会有所帮助.

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

但是,当您想要使用反向关系或预取等功能时,我不会将许多通用限定为"使用现有工具易于实现".

第三方应用程序django-genericm2m很不错,但我认为有几个缺点(默认情况下'through'对象都在同一个数据库表中,并且你没有'add'/'remove'方法 - 因此批量添加/删除).

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