Domanda

Usando Django costruito in modelli, come potrebbe creare una tripla giunzione tra i tre modelli.

Per esempio:

  • Gli utenti, i Ruoli e gli Eventi sono i modelli.
  • Gli utenti hanno molti Ruoli, e i Ruoli di molti Utenti.(ManyToMany)
  • Gli eventi hanno molti Utenti, e gli Utenti di molti Eventi.(ManyToMany)
  • Ma per ogni Evento, ogni Utente può avere un solo Ruolo.

Come può questo essere rappresentato nel modello?

È stato utile?

Soluzione

zacherates scrive:

Mi piacerebbe il Ruolo di modello di come una classe di associazione tra gli Utenti e i Ruoli (...)

Vorrei anche reccomed questa soluzione, ma si può anche fare uso di alcuni sintattica zucchero forniti da Django: ManyToMany relazione con campi aggiuntivi.

Esempio:

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)

Altri suggerimenti

Mi raccomando solo di creare un modello separato per questo.

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

Questo permette di fare tutte le solite modello di roba, come

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

L'unica cosa che rimane è quello di applicare un-ruolo-per-utenti-per-evento di restrizione.Si può fare questo nella classe di Assegnazione da sovrascrivere il metodo save (http://docs.djangoproject.com/en/dev/topics/db/models/#overriding-predefined-model-methods) o l'utilizzo di segnali (http://docs.djangoproject.com/en/dev/topics/signals/)

Mi piacerebbe il Ruolo di modello di come una classe di associazione tra gli Utenti e i Ruoli, così,

class User(models.Model):
     ...

class Event(models.Model):
     ...

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

E applicare un ruolo per ogni utente per ogni evento o di un manager o di SQL vincoli.

Pur cercando di trovare un più veloce di tre join di tabelle per il mio Django modelli, mi sono imbattuto in questa domanda.Per impostazione predefinita, Django 1.1 utilizza INNER Join che può essere lenta in InnoDB.Per una query del tipo:

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

questo potrebbe creare il seguente 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"

L'INNER Join può essere molto lento rispetto a LEFT Join.Ancora più veloce di query può essere trovato sotto gimg1 risposta: Mysql query per unire tre tabelle

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"

Tuttavia, sarà necessario utilizzare una query SQL personalizzata: https://docs.djangoproject.com/en/dev/topics/db/sql/

In questo caso, sarebbe qualcosa di simile:

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()]
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top