Created
September 1, 2009 20:06
-
-
Save mmalone/179338 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class FriendDescriptor(object): | |
""" | |
A descriptor that provides access to a user's friends. | |
""" | |
def __get__(self, instance, cls): | |
if not instance: | |
raise AttributeError('Manager must be accessed via instance') | |
Relationship = get_model('friends', 'Relationship') | |
class RelationshipManager(models.Manager): | |
def get_query_set(self): | |
User = get_model('twitterauth', 'User') | |
return User._default_manager.filter(follower_relationships__user=instance, | |
follower_relationships__reciprocal=True) | |
def request(self, user): | |
rel, created = Relationship.objects.get_or_create(user=instance, to_user=user) | |
if not created and rel.declined: | |
# If there's an existing declined request make it not declined so it | |
# appears again. | |
rel.declined = False | |
rel.save() | |
def decline(self, user): | |
try: | |
relationship = user.following_relationships.get(to_user=instance) | |
relationship.declined = True | |
relationship.save() | |
except ObjectDoesNotExist: | |
pass | |
def remove(self, user): | |
try: | |
relationship = instance.following_relationships.get(to_user=user) | |
relationship.delete() | |
except ObjectDoesNotExist: | |
pass | |
return RelationshipManager() | |
def get_friend_request_queryset(superclass, to_user): | |
class FriendRequestQuerySet(superclass): | |
def _get_friend_request(self, user): | |
return FriendRequest(user, to_user) | |
def get(self, *args, **kwargs): | |
return self._get_friend_request(super(FriendRequestQuerySet, self).get(*args, **kwargs)) | |
def latest(self, *args, **kwargs): | |
return self._get_friend_request(super(FriendRequestQuerySet, self).latest(*args, **kwargs) | |
def __getitem__(self, k): | |
if isinstance(k, slice): | |
# If it's a slice we're returning a new queryset | |
qs = super(FriendRequestQuerySet, self).__getitem__(k) | |
if isinstance(qs, (list, tuple)): | |
# If the qs has already been executed then the slice operation | |
# returns a list and we need to convert the list items, else | |
# it returns a new qs and we can just duck punch it to be the | |
# proper type. | |
return [self._get_friend_requests(i) for i in qs] | |
qs.__class__ = self.__class__ | |
return qs | |
return self._get_friend_request(super(FriendRequestQuerySet, self).__getitem__(*args, **kw | |
def __iter__(self): | |
superiter = super(FriendRequestQuerySet, self).__iter__() | |
while True: | |
yield self._get_friend_request(superiter.next()) | |
return FriendRequestQuerySet | |
class FriendRequestDescriptor(object): | |
""" | |
A descriptor that provides access to a user's friend requests. | |
""" | |
def __get__(self, instance, cls): | |
if not instance: | |
raise AttributeError('Manager must be accessed via instance') | |
User = get_model('twitterauth', 'User') | |
class FriendRequestManager(User._default_manager.__class__): | |
def get_query_set(self): | |
qs = User._default_manager.filter(following_relationships__to_user=instance, | |
following_relationships__reciprocal=False, | |
following_relationships__declined=False) | |
qs.__class__ = get_friend_request_queryset(qs.__class__, instance) | |
return qs | |
return FriendRequestManager() |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
from managers import FriendDescriptor | |
class User(models.Model): | |
username = models.CharField(max_length=40) | |
email = models.EmailField() | |
friends = FriendDescriptor() | |
friend_requests = FriendRequestDescriptor() | |
class Relationship(models.Model): | |
user = models.ForeignKey('twitterauth.User', related_name='following_relationships') | |
to_user = models.ForeignKey('twitterauth.User', related_name='follower_relationships') | |
reciprocal = models.BooleanField(default=False) | |
declined = models.BooleanField(default=False) | |
created = models.DateTimeField(auto_now_add=True, default=datetime.datetime.now) | |
modified = models.DateTimeField(auto_now=True, default=datetime.datetime.now) | |
def __unicode__(self): | |
return u'%s => %s%s' % (self.user_id, self.to_user_id, ('', ' [mutual]')[self.reciprocal]) | |
class Meta: | |
unique_together = (('user', 'to_user')) | |
class FriendRequest(models.Model): | |
def __init__(self, user, to_user): | |
self.user = user | |
self.to_user = to_user | |
def accept(self): | |
self.to_user.friends.request(self.user) | |
def decline(self): | |
self.to_user.friends.decline(self.user) | |
def relationship_save(sender, instance, **kwargs): | |
try: | |
reciprocal_rel = Relationship.objects.get(user=instance.to_user, to_user=instance.user) | |
reciprocal_rel.reciprocal = True | |
reciprocal_rel.declined = False | |
reciprocal_rel.save() | |
instance.reciprocal = True | |
_add_frempties(instance.to_user, instance.user) | |
_add_frempties(instance.user, instance.to_user) | |
except Relationship.DoesNotExist: | |
pass | |
models.signals.pre_save.connect(relationship_save, sender=Relationship, dispatch_uid=relationship_save.__name__) | |
def relationship_delete(sender, instance, **kwargs): | |
try: | |
reciprocal_rel = Relationship.objects.get(user=instance.to_user, to_user=instance.user) | |
reciprocal_rel.reciprocal = False | |
reciprocal_rel.declined = True | |
reciprocal_rel.save() | |
_remove_frempties(instance.to_user, instance.user) | |
_remove_frempties(instance.user, instance.to_user) | |
except Relationship.DoesNotExist: | |
pass | |
models.signals.post_delete.connect(relationship_delete, sender=Relationship, dispatch_uid=relationship_delete.__name__) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment