如何使用Django创建三重连接表

时间:2008-09-16 14:31:22

标签: python django model-view-controller model

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

例如:

  • 用户,角色和事件就是模型。
  • 用户有很多角色,而且角色很多用户。 (多对多)
  • 事件有很多用户,用户有很多事件。 (多对多)
  • 但对于任何给定的事件,任何用户可能只有一个角色。

如何在模型中表示?

4 个答案:

答案 0 :(得分:8)

zacherates 写道:

  

我将角色建模为用户和角色(...)之间的关联类

我也推荐这个解决方案,但你也可以使用Django提供的一些语法糖:ManyToMany relation with extra fields

示例:

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)

答案 1 :(得分:3)

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

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/

在Assignment类中执行此操作

答案 2 :(得分:0)

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

class User(models.Model):
     ...

class Event(models.Model):
     ...

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

并在管理员或SQL约束中为每个事件强制执行每个用户一个角色。

答案 3 :(得分:0)

在尝试为我自己的Django模型找到更快的三表连接时,我遇到了这个问题。默认情况下,Django 1.1使用INNER JOIN,这在InnoDB上可能很慢。对于像这样的查询:

def event_users(event_name):
    return User.objects.filter(roles__events__name=event_name)

这可能会创建以下SQL:

SELECT `user`.`id`, `user`.`name` FROM `user` INNER JOIN `roles` ON (`user`.`id` = `roles`.`user_id`) INNER JOIN `event` ON (`roles`.`event_id` = `event`.`id`) WHERE `event`.`name` = "event_name"

与LEFT JOIN相比,INNER JOIN可能会非常慢。在gimg1的答案下可以找到更快的查询:Mysql query to join three tables

SELECT `user`.`id`, `user`.`name` FROM `user`, `roles`, `event` WHERE `user`.`id` = `roles`.`user_id` AND `roles`.`event_id` = `event`.`id` AND `event`.`name` = "event_name"

但是,您需要使用自定义SQL查询:https://docs.djangoproject.com/en/dev/topics/db/sql/

在这种情况下,它看起来像:

from django.db import connection
def event_users(event_name):
    cursor = connection.cursor()
    cursor.execute('select U.name from user U, roles R, event E' \
                   ' where U.id=R.user_id and R.event_id=E.id and E.name="%s"' % event_name)
    return [row[0] for row in cursor.fetchall()]