@@ -78,7 +78,20 @@ def __init__(self, instance=None, *args, **kwargs):
78
78
super (RelationshipManager , self ).__init__ (* args , ** kwargs )
79
79
self .instance = instance
80
80
81
- def add (self , user , status = None ):
81
+ def add (self , user , status = None , symmetrical = False ):
82
+ """
83
+ Add a relationship from one user to another with the given status,
84
+ which defaults to "following".
85
+
86
+ Adding a relationship is by default asymmetrical (akin to following
87
+ someone on twitter). Specify a symmetrical relationship (akin to being
88
+ friends on facebook) by passing in :param:`symmetrical` = True
89
+
90
+ .. note::
91
+
92
+ If :param:`symmetrical` is set, the function will return a tuple
93
+ containing the two relationship objects created
94
+ """
82
95
if not status :
83
96
status = RelationshipStatus .objects .following ()
84
97
@@ -88,82 +101,108 @@ def add(self, user, status=None):
88
101
status = status ,
89
102
site = Site .objects .get_current ()
90
103
)
91
-
92
- return relationship
93
-
94
- def remove (self , user , status = None ):
104
+
105
+ if symmetrical :
106
+ return (relationship , user .relationships .add (self .instance , status , False ))
107
+ else :
108
+ return relationship
109
+
110
+ def remove (self , user , status = None , symmetrical = False ):
111
+ """
112
+ Remove a relationship from one user to another, with the same caveats
113
+ and behavior as adding a relationship.
114
+ """
95
115
if not status :
96
116
status = RelationshipStatus .objects .following ()
97
117
98
- return Relationship .objects .filter (
118
+ res = Relationship .objects .filter (
99
119
from_user = self .instance ,
100
120
to_user = user ,
101
121
status = status ,
102
122
site__pk = settings .SITE_ID
103
123
).delete ()
124
+
125
+ if symmetrical :
126
+ return (res , user .relationships .remove (self .instance , status , False ))
127
+ else :
128
+ return res
104
129
105
- def get_relationships (self , status ):
106
- return User . objects . filter (
130
+ def _get_from_query (self , status ):
131
+ return dict (
107
132
to_users__from_user = self .instance ,
108
133
to_users__status = status ,
109
- to_users__site__pk = settings .SITE_ID
134
+ to_users__site__pk = settings .SITE_ID ,
110
135
)
111
136
112
- def get_related_to (self , status ):
113
- return User . objects . filter (
137
+ def _get_to_query (self , status ):
138
+ return dict (
114
139
from_users__to_user = self .instance ,
115
140
from_users__status = status ,
116
141
from_users__site__pk = settings .SITE_ID
117
142
)
118
-
119
- def get_symmetrical (self , status ):
120
- return User .objects .filter (
121
- to_users__status = status ,
122
- to_users__from_user = self .instance ,
123
- to_users__site__pk = settings .SITE_ID ,
124
- from_users__status = status ,
125
- from_users__to_user = self .instance ,
126
- from_users__site__pk = settings .SITE_ID
127
- )
143
+
144
+ def get_relationships (self , status , symmetrical = False ):
145
+ """
146
+ Returns a QuerySet of user objects with which the given user has
147
+ established a relationship.
148
+ """
149
+ query = self ._get_from_query (status )
150
+
151
+ if symmetrical :
152
+ query .update (self ._get_to_query (status ))
153
+
154
+ return User .objects .filter (** query )
155
+
156
+ def get_related_to (self , status ):
157
+ """
158
+ Returns a QuerySet of user objects which have created a relationship to
159
+ the given user.
160
+ """
161
+ return User .objects .filter (** self ._get_to_query (status ))
128
162
129
163
def only_to (self , status ):
164
+ """
165
+ Returns a QuerySet of user objects who have created a relationship to
166
+ the given user, but which the given user has not reciprocated
167
+ """
130
168
from_relationships = self .get_relationships (status )
131
169
to_relationships = self .get_related_to (status )
132
170
return to_relationships .exclude (pk__in = from_relationships .values_list ('pk' ))
133
171
134
172
def only_from (self , status ):
173
+ """
174
+ Like :method:`only_to`, returns user objects with whom the given user
175
+ has created a relationship, but which have not reciprocated
176
+ """
135
177
from_relationships = self .get_relationships (status )
136
178
to_relationships = self .get_related_to (status )
137
179
return from_relationships .exclude (pk__in = to_relationships .values_list ('pk' ))
138
180
139
- def exists (self , user , status = None ):
140
- query = {
141
- 'to_users__from_user' : self .instance ,
142
- 'to_users__to_user' : user ,
143
- 'to_users__site__pk' : settings .SITE_ID
144
- }
145
- if status :
146
- query ['to_users__status' ] = status
147
-
148
- return User .objects .filter (** query ).count () != 0
149
-
150
- def symmetrical_exists (self , user , status = None ):
151
- query = {
152
- 'to_users__from_user' : self .instance ,
153
- 'to_users__to_user' : user ,
154
- 'to_users__site__pk' : settings .SITE_ID ,
155
- 'from_users__to_user' : self .instance ,
156
- 'from_users__from_user' : user ,
157
- 'from_users__site__pk' : settings .SITE_ID
158
- }
159
-
181
+ def exists (self , user , status = None , symmetrical = False ):
182
+ """
183
+ Returns boolean whether or not a relationship exists between the given
184
+ users. An optional :class:`RelationshipStatus` instance can be specified.
185
+ """
186
+ query = dict (
187
+ to_users__from_user = self .instance ,
188
+ to_users__to_user = user ,
189
+ to_users__site__pk = settings .SITE_ID ,
190
+ )
191
+
160
192
if status :
161
- query .update ({
162
- 'to_users__status' : status ,
163
- 'from_users__status' : status
164
- })
193
+ query .update (to_users__status = status )
194
+
195
+ if symmetrical :
196
+ query .update (
197
+ from_users__to_user = self .instance ,
198
+ from_users__from_user = user ,
199
+ from_users__site__pk = settings .SITE_ID
200
+ )
201
+
202
+ if status :
203
+ query .update (from_users__status = status )
165
204
166
- return User .objects .filter (** query ).count () != 0
205
+ return User .objects .filter (** query ).exists ()
167
206
168
207
# some defaults
169
208
def following (self ):
@@ -179,7 +218,7 @@ def blockers(self):
179
218
return self .get_related_to (RelationshipStatus .objects .blocking ())
180
219
181
220
def friends (self ):
182
- return self .get_symmetrical (RelationshipStatus .objects .following ())
221
+ return self .get_relationships (RelationshipStatus .objects .following (), True )
183
222
184
223
185
224
if django .VERSION < (1 , 2 ):
0 commit comments