def action_handler(verb, **kwargs): """ Handler function to create Action instance upon action signal call. """ kwargs.pop('signal', None) actor = kwargs.pop('sender') # We must store the unstranslated string # If verb is an ugettext_lazyed string, fetch the original string if hasattr(verb, '_proxy____args'): verb = verb._proxy____args[0] new_action = apps.get_model('activity', 'activity')( actor_content_type=ContentType.objects.get_for_model(actor), actor_object_id=actor.pk, verb=text_type(verb), created=kwargs.pop('created', now())) for opt in ('target', 'action_object'): obj = kwargs.pop(opt, None) if obj is not None: check(obj) setattr(new_action, '%s_object_id' % opt, obj.pk) setattr(new_action, '%s_content_type' % opt, ContentType.objects.get_for_model(obj)) for opt in ('is_activity', 'is_notify', 'address', 'destination'): obj = kwargs.pop(opt, None) if obj is not None: setattr(new_action, '%s' % opt, obj) if settings.USE_JSONFIELD and len(kwargs): new_action.data = kwargs new_action.save(force_insert=True) return new_action
def action_object(self, obj, **kwargs): """ Stream of most recent actions where obj is the action_object. Keyword arguments will be passed to Action.objects.filter """ check(obj) return obj.action_object_actions.public(**kwargs)
def follow(user, obj, send_action=True, actor_only=True, flag='', **kwargs): """ Creates a relationship allowing the object's activities to appear in the user's stream. Returns the created ``Follow`` instance. If ``send_action`` is ``True`` (the default) then a ``<user> started following <object>`` action signal is sent. Extra keyword arguments are passed to the action.send call. If ``actor_only`` is ``True`` (the default) then only actions where the object is the actor will appear in the user's activity stream. Set to ``False`` to also include actions where this object is the action_object or the target. If ``flag`` not an empty string then the relationship would marked by this flag. Example:: follow(request.user, group, actor_only=False) follow(request.user, group, actor_only=False, flag='liking') """ check(obj) instance, created = apps.get_model( 'activity', 'follow').objects.get_or_create( user=user, object_id=obj.pk, flag=flag, content_type=ContentType.objects.get_for_model(obj), actor_only=actor_only) return instance
def un_follow(user, obj, send_action=False, flag=''): """ Removes a "follow" relationship. Set ``send_action`` to ``True`` (``False is default) to also send a ``<user> stopped following <object>`` action signal. Pass a string value to ``flag`` to determine which type of "follow" relationship you want to remove. Example:: unfollow(request.user, other_user) unfollow(request.user, other_user, flag='watching') """ check(obj) qs = apps.get_model('activity', 'follow').objects.filter( user=user, object_id=obj.pk, content_type=ContentType.objects.get_for_model(obj)) if flag: qs = qs.filter(flag=flag) qs.delete() if send_action: action.send(user, verb=verbs.UN_FOLLOWED, target=obj)
def model_actions(self, model, **kwargs): """ Stream of most recent actions by any particular model """ check(model) ctype = ContentType.objects.get_for_model(model) return self.public( (Q(target_content_type=ctype) | Q(action_object_content_type=ctype) | Q(actor_content_type=ctype)), **kwargs)
def total_following(obj, flag=''): check(obj) qs = apps.get_model('activity', 'follow').objects.filter( object_id=obj.pk, content_type=ContentType.objects.get_for_model(obj)) if flag: qs = qs.filter(flag=flag) return qs.count()
def for_object(self, instance, flag=''): """ Filter to a specific instance. """ check(instance) content_type = ContentType.objects.get_for_model(instance).pk queryset = self.filter(content_type=content_type, object_id=instance.pk) if flag: queryset = queryset.filter(flag=flag) return queryset
def followers_qs(self, actor, flag=''): """ Returns a queryset of User objects who are following the given actor (eg my followers). """ check(actor) queryset = self.filter( content_type=ContentType.objects.get_for_model(actor), object_id=actor.pk).select_related('user') if flag: queryset = queryset.filter(flag=flag) return queryset
def any(self, obj, **kwargs): """ Stream of most recent actions where obj is the actor OR target OR action_object. """ check(obj) ctype = ContentType.objects.get_for_model(obj) return self.public( Q( actor_content_type=ctype, actor_object_id=obj.pk, ) | Q( target_content_type=ctype, target_object_id=obj.pk, ) | Q( action_object_content_type=ctype, action_object_object_id=obj.pk, ), **kwargs)
def following_qs(self, user, *models, **kwargs): """ Returns a queryset of actors that the given user is following (eg who im following). Items in the list can be of any model unless a list of restricted models are passed. Eg following(user, User) will only return users following the given user """ qs = self.filter(user=user) ctype_filters = Q() for model in models: check(model) ctype_filters |= Q( content_type=ContentType.objects.get_for_model(model)) qs = qs.filter(ctype_filters) flag = kwargs.get('flag', '') if flag: qs = qs.filter(flag=flag) return qs.fetch_generic_relations('follow_object')
def user(self, obj, with_user_activity=False, follow_flag=None, **kwargs): """Create a stream of the most recent actions by objects that the user is following.""" q = Q() qs = self.public() if not obj: return qs.none() check(obj) if with_user_activity: q = q | Q( actor_content_type=ContentType.objects.get_for_model(obj), actor_object_id=obj.pk) follows = apps.get_model('actstream', 'follow').objects.filter(user=obj) if follow_flag: follows = follows.filter(flag=follow_flag) content_types = ContentType.objects.filter( pk__in=follows.values('content_type_id')) if not (content_types.exists() or with_user_activity): return qs.none() for content_type in content_types: object_ids = follows.filter(content_type=content_type) q = q | Q( actor_content_type=content_type, actor_object_id__in=object_ids.values('object_id')) | Q( target_content_type=content_type, target_object_id__in=object_ids.filter( actor_only=False).values('object_id')) | Q( action_object_content_type=content_type, action_object_object_id__in=object_ids.filter( actor_only=False).values('object_id')) return qs.filter(q, **kwargs)
def is_following(user, obj, flag=''): """ Checks if a "follow" relationship exists. Returns True if exists, False otherwise. Pass a string value to ``flag`` to determine which type of "follow" relationship you want to check. Example:: is_following(request.user, group) is_following(request.user, group, flag='liking') """ check(obj) qs = apps.get_model('activity', 'follow').objects.filter( user=user, object_id=obj.pk, content_type=ContentType.objects.get_for_model(obj)) if flag: qs = qs.filter(flag=flag) return qs.exists()