views:

2611

answers:

1

I want to store which user invited another user to a group... but django is telling me this is ambigous and against the rules (which makes sense).

groups.group: Intermediary model Group_to_Member has more than one foreign key to User, which is ambiguous and is not permitted.

So how do I do this correctly? Maybe a generic relation? might work but seems a bit convoluted... Here's how I was approaching it (with unrelated bits removed)

from django.contrib.auth.models import User

class UserGroup(models.Model):
    members = models.ManyToManyField(User, through='Group_to_Member')

class UserGroup_to_Member(models.Model):
    group = models.ForeignKey(UserGroup)
    member = models.ForeignKey(User)

    invited_by = models.ForeignKey(User, related_name="group_invited_users")

Solution

Ok so I did a little combination of the answers you guys provided (Thanks!) and things I found on the internet plus my own admittedly meager python-fu:

from django.contrib.auth.models import User

class UserGroup(models.Model):
    # notice there is no member object here
    ... other model data

    def add_member(self, **kwargs):
        g2m = UserGroup_to_Member(group = self,  **kwargs)
        g2m.save()

    def remove_member(self, member):
        g2m = UserGroup_to_Member.objects.get(group=self, member=member)
        g2m.delete()

    # This is not elegant at all, help please? I'm pretty sure it isn't
    # as bad on the database as it looks though.
    def get_members(self):
        g2ms = UserGroup_to_Member.objects.filter(group=self)
        member_ids = [g2m.member.id for g2m in g2ms]
        members = User.objects.none()
        for id in member_ids:
            members = members | User.objects.get(id=id)
        return members


class UserGroup_to_Member(models.Model):
    group = models.ForeignKey(UserGroup)
    member = models.ForeignKey(User)

    invited_by = models.ForeignKey(User, related_name="group_invited_users")
+3  A: 

You have to manage it yourself:

class MyGroup(models.Model):
    name = models.CharField(max_length=100)

class Membership(models.Model):
    group = models.ForeignKey(MyGroup)
    member = models.ForeignKey(User)

    invited_by = models.ForeignKey(User, related_name='invited_set')

Then instead of group.members.all() you do group.membership_set.all().

Also, I wouldn't use 'Group' as your model name, as Django already has a Group object.

Graham King
Thanks for the tip on the model name, but your solution does not use a many-to-many relation
Jiaaro
also... group.members.all() returns a queryset of User objects, whereas group.membership_set.all() returns a queryset of Membership objects
Jiaaro
the only way to get a list of group members using that method is member_list = [m.member for m in Membership.objects.filter(group=group)]
Jiaaro