正确使用django中具有自引用外键的子类/代理?

时间:2014-11-18 17:10:34

标签: python django inheritance relational-database django-contenttypes

我有两个班,有一个超级班。本质上,这两个类是树上的具体类。一个是叶子,一个是分支。它们共享超类中定义的属性。

以下所有课程均未完成。我尝试过制作超类摘要和子类代理。希望下面的代码解释了我想要实现的目标。

这是超级班级'

class Owner(models.Model):
    name = models.CharField(max_length=200)
    def __unicode__(self):
        return self.name
    class Meta:
        abstract=True

这是' leaf'

class User(Owner):
    pass

这是'分支'。

class Group(Owner):
    head = models.ForeignKey(User)
    members = models.ManyToManyField(Owner,through='Membership')

这显示了用户如何通过成员资格属于某个组。

class Membership(models.Model):
    date_joined = models.DateField()
    user = models.ForeignKey(Owner)
    group = models.ForeignKey(Group)

我的限制是每个用户都可以属于多个组(通过链接器Membership)。每个小组都可以是一个小组的成员。

这是失败的,因为我在作为用户的成员身份和组成员中引用了所有者。我觉得这是我用Java中的泛型来解决的问题,但这不会对我有所帮助。

我还看到ContentTypes用于此排序的东西,但它们似乎太复杂了我想要做的事情。我错了吗?我无法弄清楚如何将这个范例应用到我的例子中。我还发现了this问题,但我仍然不确定应该如何实施。

1 个答案:

答案 0 :(得分:1)

您不能将外键字段指向抽象类(数据库中没有抽象类的表)。

您可能需要为每个Group实现自引用外键,使其属于零个或一个组。像这样:

class Base(models.Model):
    name = models.CharField(max_length=200)
    def __unicode__(self):
        return self.name
    class Meta:
        abstract=True


class User(Base):
    groups = models.ManyToManyField('Group', through='Membership', related_name='members')


class Group(Base):
    head = models.ForeignKey(User)
    parent = models.ForeignKey('self', blank=True, null=True, related_name='children')

    def descendants(self, **kwargs):
        qs = self.children_set.filter(**kwargs)
        for group in self.children_set.all():
            qs = qs | group.descendants(**kwargs)
        return qs


class Membership(models.Model):
    date_joined = models.DateField()
    user = models.ForeignKey(User)
    group = models.ForeignKey(Group)

上面的Base类除了要求每个继承的类在其各自的数据库表和name方法中都有__unicode__字段之外别无其他 - 仅此而已。您只需将name字段和__unicode__方法复制并粘贴到UserGroup即可,功能相同。拥有一个公共抽象父级不会创建任何数据库关系,也不能使用它来查询数据库。

在这种情况下我无法真正看到使用代理类的原因。