[python] Djangoで三重結合テーブルを作成する方法


Answers

私はちょうどこれのための完全に別のモデルを作成することをお勧めしたい。

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

残っている唯一のことは、イベントごとのユーザー制限ごとに1つの役割を果たすことです。 これは、saveメソッド( http://docs.djangoproject.com/ja/dev/topics/db/models/#overriding-predefined-model-methods )をオーバーライドするか、シグナル( http: //docs.djangoproject.com/ja/dev/topics/signals/

Question

Djangoの組み込みモデルを使用すると、3つのモデル間でどのように三重結合を作成できますか?

例えば:

  • ユーザー、ロール、およびイベントはモデルです。
  • ユーザーには多くの役割があり、役割には多くのユーザーがいます。 (ManyToMany)
  • イベントには多くのユーザーとユーザーがいます。 (ManyToMany)
  • しかし、任意のイベントに対して、どのユーザも1つの役割しか持たないことがあります。

これをモデルでどのように表現できますか?




私自身のDjangoモデルのためのより速い3テーブル結合を見つけることを試みている間に、私はこの質問に出くわしました。 デフォルトでは、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"

INNER JOINはLEFT JOINと比較して非常に遅くなる可能性があります。 もっと速いクエリはgimg1の答えで見つけることができます: 3つのテーブルを結合する 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()]





Links