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

例如:

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

如何在模型中表示这一点?

有帮助吗?

解决方案

萨切拉特 写道:

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

我也推荐了这个解决方案,但你也可以使用 Django 提供的一些语法糖: 具有额外字段的多对多关系.

例子:

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)

其他提示

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

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")

剩下的唯一一件事就是强制执行每个用户每个事件一个角色的限制。您可以通过重写 save 方法(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 约束中强制每个用户每个事件一个角色。

在尝试为我自己的 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查询连接三张表

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()]
许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top