What is the best way to model friendships between users for a social networking site?
The possible states are:
- no Friendship
- FriendRequest from A to B, B needs to confirm (this is asymmetric)
- A and B are friends (this is symmetric)
now its complicated to choose the models right.
My Friends are part of my profile
quite obvious, A.profile.friends is a many to many relation to other users.
- no friendship: B not in A.friends and A not in B.friends
- A requests friendship with B: B in A.friends
- Friends: B in A.friends and A in B.friends
but it seems to be rather unclean to merge the friend with the friendrequest relation. and without this merge, the data is redundant, because then "A in B.friends and not B in A.friends" would be an undefined state.
Friend-Lookup: A.friends.filter(friends__contains=B) #rather complicated lookup on db level, unintuitive for coders
Seperate tables
FriendRequest is quite obvious, a class with requester and requested_user, the selects are quite obvious, too.
The Friend Model would be not very nice, because it would have person1 and person2 as fields, and all lookups need to select Friends with person1=A and person2=B OR person1=B and person2=A
Friend-Lookup: Friend.objects.filter(person1=A) union Friend.objects.filter(person2=A) #unclean with the need to union two sets
Seperate many2many table
another option would be a Friend model with a friends field, which is a many2many field, which links to exactly two persons. Then the select is matching one of the persons in the friends field, and then just returns the model, where the person B can be extrated by substracting A from the friends set. But this would be overkill, because no friend-object would ever have more than 2 persons associated.
Friend-Lookup: Friendship.objects.filter(persons__contains=A) #queries two tables
So, what do you think is the cleanest and most intuitive solution to storing a friendship-relation? Are there any common patterns how to do it?