Hoe om 'n te skep trippel-sluit tafel met Django
-
09-06-2019 - |
Vra
Die gebruik van Django se gebou in modelle, hoe sou 'n mens skep 'n drie-sluit tussen drie modelle.
Byvoorbeeld:
- Gebruikers, rolle, en gebeure is die modelle.
- Gebruikers het baie rolle, en rolle baie gebruikers. (ManyToMany)
- Events het baie gebruikers, en gebruikers baie Events. (ManyToMany)
- Maar vir enige gegewe Event, kan enige gebruiker net een rol.
Hoe kan dit verteenwoordig in die model?
Oplossing
zacherates skryf:
Ek sal rol as 'n vereniging klas tussen gebruikers en rolle (...)
'n model
Ek wil ook reccomed hierdie oplossing, maar jy kan ook gebruik maak van 'n paar sintaktiese suiker verskaf deur Django maak: ManyToMany verhouding met ekstra velde .
Voorbeeld:
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)
Ander wenke
Ek wil aanbeveel net die skep van 'n heeltemal aparte model vir hierdie.
class Assignment(Model):
user = ForeignKey(User)
role = ForeignKey(Role)
event = ForeignKey(Event)
Dit laat jou doen al die gewone model dinge, soos
user.assignment_set.filter(role__name="Chaperon")
role.assignment_set.filter(event__name="Silly Walkathon")
Die enigste ding wat links is om jou een-rol per gebruiker per gebeurtenis-beperking af te dwing. Jy kan dit doen in die Opdrag klas deur óf oorheersende die red metode ( http://docs.djangoproject.com/en/dev/topics/db/models/#overriding-predefined-model-methods ) of die gebruik van seine ( http://docs.djangoproject.com/en/dev/topics/signals/ )
Ek sal rolmodel as 'n vereniging klas tussen gebruikers en rolle, dus,
class User(models.Model):
...
class Event(models.Model):
...
class Role(models.Model):
user = models.ForeignKey(User)
event = models.ForeignKey(Event)
En dwing die een rol per gebruiker per gebeurtenis in óf 'n bestuurder of SQL beperkings.
Terwyl jy probeer om uit te vind 'n vinniger drie-tafel aan te sluit vir my eie Django modelle, het ek afgekom op hierdie vraag. By verstek, Django 1.1 gebruik INNER sluit wat stadig op InnoDB kan wees. Vir 'n soektog soos:
def event_users(event_name):
return User.objects.filter(roles__events__name=event_name)
dit kan die volgende SQL skep:
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 binneste sluit kan baie stadig in vergelyking met die linker sluit. 'N nog vinniger navraag kan gevind word onder gimg1 se antwoord: MySQL navraag na drie tafels aan te sluit
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"
Dit sal egter moet jy 'n persoonlike SQL navraag gebruik: https: //docs.djangoproject.com/en/dev/topics/db/sql/
In hierdie geval, sou dit iets soos kyk:
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()]