Frage

Mit Django in Modellen gebaut, wie würde man schaffen eine Triple-Verknüpfung zwischen drei Modellen.

Zum Beispiel:

  • Benutzer, Rollen und Events sind die Modelle.
  • Die Benutzer haben viele Rollen und Rollen viele Benutzer. (ManyToMany)
  • Veranstaltungen haben viele Benutzer, und Benutzer viele Veranstaltungen. (ManyToMany)
  • Aber für jedes gegebenes Ereignis, jeder Benutzer kann nur eine Rolle hat.

Wie kann dies im Modell dargestellt werden?

War es hilfreich?

Lösung

zacherates schreibt:

  

würde ich Rolle als Assoziationsklasse zwischen Benutzern und Rollen-Modell (...)

ich auch diese Lösung reccomed würde, aber Sie können auch Gebrauch machen von einigen syntaktischen Zucker von Django bereitgestellt machen: ManyToMany Beziehung mit zusätzlichen Feldern .

Beispiel:

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)

Andere Tipps

Ich würde empfehlen, nur ein völlig eigenständiges Modell dafür zu schaffen.

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

Auf diese Weise können Sie alle üblichen Modell Dinge tun, wie

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

Das einzige, was links ist Ihre One-Rolle-per-user-per-Ereignis Einschränkung zu erzwingen. Sie können entweder in der Zuordnung Klasse tun dies die Methode speichern überschrieben ( http://docs.djangoproject.com/en/dev/topics/db/models/#overriding-predefined-model-methods ) oder unter Verwendung von Signalen ( http://docs.djangoproject.com/en/dev/topics/signals/ )

I Rolle als Assoziationsklasse modellieren würde zwischen Benutzern und Rollen, so

class User(models.Model):
     ...

class Event(models.Model):
     ...

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

Und erzwingt die eine Rolle pro Benutzer pro Ereignis in entweder ein Manager oder SQL-Constraints.

Beim Versuch, eine schneller zu finden drei-Tabelle für meine eigenen Django Modelle kommt, stieß ich auf dieser Frage. Standardmäßig Django 1.1 verwendet INNER JOIN, die auf InnoDB langsam sein kann. Bei einer Abfrage wie:

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

Dies könnte erstellen Sie die folgende 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"

Die INNER JOIN kann sehr langsam sein, verglichen mit LEFT JOIN. Eine noch schnellere Abfrage kann unter gimg1 Antwort zu finden: Mysql Abfrage drei Tabellen verknüpfen

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"

Allerdings müssen Sie eine benutzerdefinierte SQL-Abfrage verwenden: https: //docs.djangoproject.com/en/dev/topics/db/sql/

In diesem Fall wäre es etwa so aussehen:

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()]
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top