Como criar um triple-se juntar a tabela com Django

votos
9

Usando Django é construído em modelos, como é que se cria um triplo-junção entre três modelos.

Por exemplo:

  • Usuários, funções e eventos são os modelos.
  • Os usuários têm muitas funções e Roles muitos usuários. (Muitos para muitos)
  • Os eventos têm muitos usuários, e Usuários muitos eventos. (Muitos para muitos)
  • Mas para qualquer evento, qualquer usuário pode ter apenas um papel.

Como isso pode ser representado no modelo?

Publicado 16/09/2008 em 15:31
fonte usuário
Em outras línguas...                            


4 respostas

votos
8

zacherates escreve:

Eu modelo como uma classe de associação entre usuários e funções (...)

Eu também reccomed esta solução, mas você também pode fazer uso de um pouco de açúcar sintático fornecido pelo Django: relação ManyToMany com campos extras .

Exemplo:

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)
Respondeu 16/09/2008 em 23:22
fonte usuário

votos
3

Eu recomendo apenas criar um modelo totalmente separado para isso.

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

Isto permite-lhe fazer todas as coisas modelo habitual, tais como

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

A única coisa que resta é fazer valer a sua restrição de um papel-per-user-per-evento. Você pode fazer isso na classe Assignment por qualquer substituindo o método salvar ( http://docs.djangoproject.com/en/dev/topics/db/models/#overriding-predefined-model-methods ) ou através de sinais ( http: //docs.djangoproject.com/en/dev/topics/signals/ )

Respondeu 16/09/2008 em 15:49
fonte usuário

votos
0

Enquanto tentando encontrar um e três de mesa mais rápido juntar-se para os meus próprios modelos do Django, me deparei com esta questão. Por padrão, o Django 1.1 usa associações internas que podem ser lento no InnoDB. Para uma consulta como:

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

isso pode criar a seguinte 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"

O associações internas podem ser muito lento em comparação com LEFT JOINs. Uma consulta ainda mais rápido pode ser encontrado sob a resposta de gimg1: consulta de mysql para se juntar três tabelas

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"

No entanto, você vai precisar usar uma consulta SQL personalizada: https://docs.djangoproject.com/en/dev/topics/db/sql/

Neste caso, seria algo parecido com:

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()]
Respondeu 30/04/2013 em 01:11
fonte usuário

votos
0

Eu modelo como uma classe de associação entre usuários e funções, assim,

class User(models.Model):
     ...

class Event(models.Model):
     ...

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

E fazer cumprir o papel por usuário por evento em qualquer um gerente ou restrições de SQL.

Respondeu 16/09/2008 em 20:51
fonte usuário

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more