如何使用Django创建三联接表

时间:2020-03-05 18:56:07  来源:igfitidea点击:

使用Django的内置模型,如何在三个模型之间创建三重联接。

例如:

  • 用户,角色和事件是模型。
  • 用户有许多角色,而角色有许多用户。 (多对多)
  • 事件有许多用户,而用户有许多事件。 (多对多)
  • 但是对于任何给定事件,任何用户都只能拥有一个角色。

该如何在模型中表示?

解决方案

回答

我建议为此创建一个完全独立的模型。

class Assignment(Model):
    user = ForeignKey(User)
    role = ForeignKey(Role)
    event = ForeignKey(Event)

这使我们可以执行所有常用的模型工作,例如

user.assignment_set.filter(role__name="Chaperon")
role.assignment_set.filter(event__name="Silly Walkathon")

剩下的唯一一件事就是强制执行每个用户每事件一个角色的限制。我们可以通过覆盖保存方法(http://docs.djangoproject.com/en/dev/topics/db/models/#overriding-predefined-model-methods)或者使用信号(http: //docs.djangoproject.com/en/dev/topics/signals/)

回答

我将角色建模为用户和角色之间的关联类,因此,

class User(models.Model):
     ...

class Event(models.Model):
     ...

class Role(models.Model):
     user = models.ForeignKey(User)
     event = models.ForeignKey(Event)

并在管理器或者SQL约束中为每个事件的每个用户强制一个角色。

回答

zacherates写道:

I'd model Role as an association class between Users and Roles (...)

我也建议使用此解决方案,但是我们也可以使用Django提供的一些语法糖:ManyToMany与其他字段的关系。

例子:

class User(models.Model):
    name = models.CharField(max_length=128)

class Event(models.Model):
    name = models.CharField(max_length=128)
    members = models.ManyToManyField(User, through='Role')

    def __unicode__(self):
        return self.name

class Role(models.Model):
    person = models.ForeignKey(User)
    group = models.ForeignKey(Event)
    date_joined = models.DateField()
    invite_reason = models.CharField(max_length=64)