I am working on a design for some models in Django and wanted to get some advice. I have a model for teams, of which many users can be a part of. The users can also be members of many teams, but they cannot be members of the same team twice. There is also separate information I want to track for each team/user combo. On top of that, there will be a user who is an "admin" for each team, but each team may have only a single admin. I have some condensed data model definitions as follows:
class Team(models.Model):
name = models.CharField()
members = models.ManyToManyField(User, through='Membership')
admin = models.ForeignKey(User)
class Membership(models.Model):
user = models.ForeignKey(Us开发者_如何学JAVAer)
team = models.ForeignKey(Team)
extra_data = models.CharField()
So I guess my two questions are:
1) how would I make it so that on the Membership model, no user and team combination appeared more than once?
2) Is there a better way to signify an Admin on the team, while making sure that each team only had a single one? It seems like if I'm storing the admin like this, while enforcing the rule of having only a single admin, it becomes too cumbersome to query all team members since the admin will not be in the Membership table. And if they are stored in membership, than I'd have to perform another query to see if they are admin of this team or not. The thought of using an "is_admin" field in Membership popped in my head, but I'm unsure of how to keep the constraints of 1 admin per team.
Any help would be greaty appreciated.
UPDATE: looks like the unique_together meta tag is what I'm looking for on the first question. I'm still curious about the second one though....
First question:
You can add a constraint to prevent it:
class Membership(models.Model):
user = models.ForeignKey(User)
team = models.ForeignKey(Team)
extra_data = models.CharField()
class Meta:
unique_together = (('user','team'),)
Second question(s):
You could add a ranking field to the membership model and make 'user' and 'rank' unique_together, positive integer field. And user with rank == 1
is the admin. Or similar. It will be enforcing your scheme, but can be cumbersome to code the maintenance of it. You may well be better off with what you've got.
In response to your second question:
Why wouldn't you include the admin in the team's members m2m?
When you want the entire teaming including the admin:
some_team.members
Keeping the admin fk on the team model makes sense, when you want the admin you can use:
some_team.admin
and when you want the team without the admin you can use:
some_team.members.exclude(pk = some_team.admin.pk)
精彩评论