2008-09-16 51 views
9

使用Django內置的模型,如何在三個模型之間創建三連接。如何使用Django創建三連接表

例如:

  • 用戶,角色和事件模型。
  • 用戶有很多角色,並且角色很多用戶。 (ManyToMany)
  • 事件有很多用戶,而用戶有很多事件。 (ManyToMany)
  • 但是對於任何給定的事件,任何用戶可能只有一個角色。

這怎麼可以在模型中表示?

回答

8

zacherates寫道:

我模範作用爲用戶和角色之間的關聯類(...)

我還reccomed此解決方案,但你可以還可以使用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) 
+0

在Django中這是相當新的(從1.0開始)。 – zgoda 2008-09-17 10:05:13

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

的唯一剩下的就是執行您的一個角色,每個用戶每次事件的限制。您可以通過在Assignment類爲此重寫保存方法(http://docs.djangoproject.com/en/dev/topics/db/models/#overriding-predefined-model-methods)或使用的信號(http://docs.djangoproject.com/en/dev/topics/signals/

0

我模式中的角色作爲用戶和角色,從而之間的關聯的類,

class User(models.Model): 
    ... 

class Event(models.Model): 
    ... 

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

並在管理器或SQL約束中爲每個用戶每個事件強制執行一個角色。

0

雖然試圖找到一個更快的三表連接爲自己的Django模型,我碰到這個問題。默認情況下,Django 1.1使用InnoDB上的INNER JOIN。對於像查詢:

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的可能會很慢。更快的查詢可以在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()]