views:

405

answers:

1

Preface: I am new to django and to db design.

SUPEREDIT: I made some significant changes, so the answers before my changes may reference things not here. I apologize.

I'll get right to the code: models.py:

class Player(models.Model):
    name = models.CharField()

class Team(models.Model):
    name = models.CharField()
    members = models.ManyToManyField(Player, through='Membership')

class Word(models.Model):
    word = models.CharField(unique=True)
    definition = models.CharField()
    ...

class Ownership(models.Model):
    owner = models.ForeignKey(Player)
    team = models.ForeignKey(Team)
    word = models.ForeignKey(Word)

class Membership(models.Model):
    team = models.ForeignKey(Team)
    player = models.ForeignKey(Player)

the Word table has been populated. In the admin I create a Player. I then create a team and add members to it. I've added Ownership to the admin. I create a new Ownership and I get to pick from players, from the teams, and from the words. I'd like to put a constraint where if a player owns a word for a given team, then players belonging to that team can not own the word within the team. They may own the word in other teams.

The way it is now. I could have two different players on the same team own the same word. Bad. Basically I want the admin to say take all of the words owned within this team and not make them available in the drop down.

How can I model this relationship? How can I get this functionality in the admin?

EDIT: I added the membership model just to show that I am trying to solve a different problem. And as I said, this is a simplified example of what I am really working with. As you can see I've got the membership relationship done, I am trying to solve a separate problem of ownership.

+1  A: 

Your schema is incorrect. You should be making use of "Extra fields on Many-to-Many relationships" as seen here in the Django docs.

It is also highlighted here on SO.

Look into unique_together for your "team-number" association. I'm not sure if it will also work in conjunction with the extra fields on the many-to-many approach. Otherwise, you could enforce the uniqueness in the view, but I do believe unique_together should work in your case.

For the 1-99 limitation, you should just include this in your form validation, and in conjunction with a uniqueness check, you do not need an entire table just to store the numbers 1-99.

Update for your edit

I'm not sure you actually read my post or followed any of my links but it solves exactly the problem you described, unless of course you still haven't explained the problem correctly. "Ownership" of a number is not something you should be modeling, you should be expressing it where it belongs:

class Player(models.Model):
    name = models.CharField(max_length=128)

    def __unicode__(self):
        return self.name

class Team(models.Model):
    name = models.CharField(max_length=128)
    players = models.ManyToManyField(Player, through='Membership')

    def __unicode__(self):
        return self.name

class Membership(models.Model):
    player = models.ForeignKey(Player)
    team = models.ForeignKey(Team)
    number = models.IntegerField()
    """ ... """

    class Meta:
        unique_together = ('team', 'number')

So please explain to me again how you need an Ownership model for Player-Team-Number associations, because I'm not sure what exactly you're trying to achieve that is separate from what I already provided you.

jonwd7
I'm not trying to solve membership. I've updated my question with further information to hopefully clarify what I am trying to get at. Remember this is a simplified made up schema to model what I am dealing with.
Dan.StackOverflow
Updated. I'm pretty sure I was already getting at exactly what you needed, pre-clarification. :)
jonwd7
I think my example is poorly illustrating what I am trying to do. I appreciate your help and patience. Before I go and rip out everything I have, imagine a player can pick multiple numbers as time goes by. I think that scenario would clutter the membership table. Which is why I was trying to separate it. but I think the unique_together thing is just what I was looking for. I will play with it.
Dan.StackOverflow
Have to agree with jon.wd7 here. His schema makes more sense. The Ownership and Number tables are redundant. The number should be a field of the Membership relationship. This way the uniqueness of each number is enforced per team.
sixthgear