Using Django's built in models, how would one create a triple-join between three models.
For example:
- Users, Roles, and Events are the models.
- Users have many Roles, and Roles many Users. (ManyToMany)
- Events have many Users, and Users many Events. (ManyToMany)
- But for any given Event, any User may have only one Role.
How can this be represented in the model?
-
I'd recommend just creating an entirely separate model for this.
class Assignment(Model): user = ForeignKey(User) role = ForeignKey(Role) event = ForeignKey(Event)This lets you do all the usual model stuff, such as
user.assignment_set.filter(role__name="Chaperon") role.assignment_set.filter(event__name="Silly Walkathon")The only thing left is to enforce your one-role-per-user-per-event restriction. You can do this in the Assignment class by either overriding the save method (http://docs.djangoproject.com/en/dev/topics/db/models/#overriding-predefined-model-methods) or using signals (http://docs.djangoproject.com/en/dev/topics/signals/)
From Eli Courtwright -
I'd model Role as an association class between Users and Roles, thus,
class User(models.Model): ... class Event(models.Model): ... class Role(models.Model): user = models.ForeignKey(User) event = models.ForeignKey(Event)And enforce the one role per user per event in either a manager or SQL constraints.
From Aaron Maenpaa -
zacherates writes:
I'd model Role as an association class between Users and Roles (...)
I'd also reccomed this solution, but you can also make use of some syntactical sugar provided by Django: ManyToMany relation with extra fields.
Example:
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)zgoda : This is quite new in Django (since 1.0).From zuber
0 comments:
Post a Comment