Beispiel #1
0
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]

    newaction = apps.get_model('actstream', 'action')(
        actor_content_type=ContentType.objects.get_for_model(actor) if actor is not None else None,
        actor_object_id=actor.pk if actor is not None else None,
        verb=str(verb),
        public=bool(kwargs.pop('public', True)),
        description=kwargs.pop('description', None),
        timestamp=kwargs.pop('timestamp', now())
    )

    for opt in ('target', 'action_object'):
        obj = kwargs.pop(opt, None)
        if obj is not None:
            check(obj)
            setattr(newaction, '%s_object_id' % opt, obj.pk)
            setattr(newaction, '%s_content_type' % opt,
                    ContentType.objects.get_for_model(obj))
    if settings.USE_JSONFIELD and len(kwargs):
        newaction.data = kwargs
    newaction.save(force_insert=True)
    return newaction
Beispiel #2
0
 def actor(self, obj, **kwargs):
     """
     Stream of most recent actions where obj is the actor.
     Keyword arguments will be passed to Action.objects.filter
     """
     check(obj)
     return obj.actor_actions.public(**kwargs)
Beispiel #3
0
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('actstream', '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
    )
    if send_action and created:
        if not flag:
            action.send(user, verb=_('started following'), target=obj, **kwargs)
        else:
            action.send(user, verb=_('started %s' % flag), target=obj, **kwargs)
    return instance
Beispiel #4
0
 def for_object(self, instance):
     """
     Filter to a specific instance.
     """
     check(instance)
     # content_type = ContentType.objects.get_for_model(instance).pk
     return self.filter(follow_object_id=instance.pk)
Beispiel #5
0
def follow(user, obj, send_action=True, actor_only=True, **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.

    Example::

        follow(request.user, group, actor_only=False)
    """
    check(obj)
    instance, created = get_model('actstream', 'follow').objects.get_or_create(
        user=user, follow_object_id=obj.pk,
        actor_only=actor_only)
    if send_action and created:
        action.send(user, verb=_('started following'), target=obj, **kwargs)
    return instance
 def for_object(self, instance):
     """
     Filter to a specific instance.
     """
     check(instance)
     content_type = ContentType.objects.get_for_model(instance).pk
     return self.filter(content_type=content_type, object_id=instance.pk)
Beispiel #7
0
    def mystream(self, obj, **kwargs):
        """
        Custom stream for users. Includes votes and comments info.
        """
        q = Q()
        check(obj)

        objects_by_content_type = defaultdict(lambda: [])

        following = (
            get_model("actstream", "follow").objects.filter(user=obj).values_list("content_type_id", "object_id")
        )

        if not len(following):
            return self.none()

        for content_type_id, object_id in following.iterator():
            objects_by_content_type[content_type_id].append(object_id)

        for content_type_id, object_ids in objects_by_content_type.items():
            q = (
                q
                | Q(actor_content_type=content_type_id, actor_object_id__in=object_ids)
                | Q(target_content_type=content_type_id, target_object_id__in=object_ids)
                | Q(action_object_content_type=content_type_id, action_object_object_id__in=object_ids)
            )

        return self.filter(q, **kwargs)
Beispiel #8
0
 def related_action_object(self, obj, **kwargs):
     """
     Stream of most recent actions where obj is the related action_object.
     Keyword arguments will be passed to Action.objects.filter
     """
     check(obj)
     return obj.related_action_object_actions.public(**kwargs)
 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, **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.

    Example::

        follow(request.user, group, actor_only=False)
    """
    check(obj)
    instance, created = get_model('actstream', 'follow').objects.get_or_create(
        user=user, object_id=obj.pk,
        content_type=ContentType.objects.get_for_model(obj),
        actor_only=actor_only)
    if send_action and created:
        action.send(user, verb=_('started following'), target=obj, **kwargs)
    return instance
def unfollow(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('actstream', '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:
        if not flag:
            action.send(user, verb=_('stopped following'), target=obj)
        else:
            action.send(user, verb=_('stopped %s' % flag), target=obj)
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]

    newaction = get_model('actstream', 'action')(
        actor_content_type=ContentType.objects.get_for_model(actor),
        actor_object_id=actor.pk,
        verb=text_type(verb),
        public=bool(kwargs.pop('public', True)),
        description=kwargs.pop('description', None),
        timestamp=kwargs.pop('timestamp', now())
    )

    for opt in ('target', 'action_object'):
        obj = kwargs.pop(opt, None)
        if obj is not None:
            check(obj)
            setattr(newaction, '%s_object_id' % opt, obj.pk)
            setattr(newaction, '%s_content_type' % opt,
                    ContentType.objects.get_for_model(obj))
    if settings.USE_JSONFIELD and len(kwargs):
        newaction.data = kwargs
    newaction.save(force_insert=True)
    return newaction
def unfollow(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('actstream', '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:
        if not flag:
            action.send(user, verb=_('stopped following'), target=obj)
        else:
            action.send(user, verb=_('stopped %s' % flag), target=obj)
Beispiel #14
0
    def mystream(self, obj, **kwargs):
        """
        Custom stream for users. Includes votes and comments info.
        """
        q = Q()
        check(obj)

        objects_by_content_type = defaultdict(lambda: [])

        following = get_model('actstream', 'follow').objects\
            .filter(user=obj).values_list('content_type_id', 'object_id', )

        if not len(following):
            return self.none()

        for content_type_id, object_id in following.iterator():
            objects_by_content_type[content_type_id].append(object_id)

        for content_type_id, object_ids in objects_by_content_type.items():
            q = q | Q(
                actor_content_type=content_type_id,
                actor_object_id__in=object_ids,
            ) | Q(
                target_content_type=content_type_id,
                target_object_id__in=object_ids,
            ) | Q(
                action_object_content_type=content_type_id,
                action_object_object_id__in=object_ids,
            )

        return self.filter(q, **kwargs)
Beispiel #15
0
 def followers_qs(self, actor):
     """
     Returns a queryset of User objects who are following the given actor (eg my followers).
     """
     check(actor)
     return self.filter(
         content_type=ContentType.objects.get_for_model(actor),
         object_id=actor.pk).select_related('user')
Beispiel #16
0
def unfollow(user, obj, ftype, send_action=True):
    check(obj)
    Follow.objects.filter(user=user,
                          object_id=obj.pk,
                          content_type=ContentType.objects.get_for_model(obj),
                          ftype=ftype).delete()

    if send_action:
        action.send(user, verb='un%s' % ftype, 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 followers_qs(self, actor):
     """
     Returns a queryset of User objects who are following the given actor (eg my followers).
     """
     check(actor)
     return self.filter(
         content_type=ContentType.objects.get_for_model(actor),
         object_id=actor.pk
     ).select_related('user')
 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
     )
Beispiel #20
0
 def followers(self, actor):
     """
     Returns a list of User objects who are following the given actor (eg my followers).
     """
     check(actor)
     return [
         follow.user for follow in self.filter(
             follow_object_id=actor.pk).select_related('user')
     ]
Beispiel #21
0
 def for_object(self, instance, follow_type=None):
     """
     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 follow_type:
         queryset = queryset.filter(follow_type=follow_type)
     return queryset
 def following(self, user, *models):
     """
     Returns a list 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)
     for model in models:
         check(model)
         qs = qs.filter(content_type=ContentType.objects.get_for_model(model))
     return [follow.follow_object for follow in qs.fetch_generic_relations('follow_object')]
 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
     )
Beispiel #24
0
 def following_qs(self, user, *models):
     """
     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)
     return qs.fetch_generic_relations('follow_object')
Beispiel #25
0
def is_following(user, obj):
    """
    Checks if a "follow" relationship exists.

    Returns True if exists, False otherwise.

    Example::

        is_following(request.user, group)
    """
    check(obj)
    return apps.get_model('actstream', 'follow').objects.filter(
        user=user,
        object_id=obj.pk,
        content_type=ContentType.objects.get_for_model(obj)).exists()
def is_following(user, obj):
    """
    Checks if a "follow" relationship exists.

    Returns True if exists, False otherwise.

    Example::

        is_following(request.user, group)
    """
    check(obj)
    return get_model('actstream', 'follow').objects.filter(
        user=user, object_id=obj.pk,
        content_type=ContentType.objects.get_for_model(obj)
    ).exists()
Beispiel #27
0
 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_id=obj.pk, ) | Q(
                 # target_content_type=ctype,
                 target_id=obj.pk, ) | Q(
                     action_object_content_type=ctype,
                     action_object_object_id=obj.pk,
                 ),
         **kwargs)
Beispiel #28
0
def unfollow(user, obj, send_action=False):
    """
    Removes a "follow" relationship.

    Set ``send_action`` to ``True`` (``False is default) to also send a
    ``<user> stopped following <object>`` action signal.

    Example::

        unfollow(request.user, other_user)
    """
    check(obj)
    get_model('actstream', 'follow').objects.filter(
        user=user, follow_object_id=obj.pk).delete()
    if send_action:
        action.send(user, verb=_('stopped following'), target=obj)
Beispiel #29
0
def unfollow(user, obj, send_action=False):
    """
    Removes a "follow" relationship.

    Set ``send_action`` to ``True`` (``False is default) to also send a
    ``<user> stopped following <object>`` action signal.

    Example::

        unfollow(request.user, other_user)
    """
    check(obj)
    apps.get_model('actstream', 'follow').objects.filter(
        user=user,
        object_id=obj.pk,
        content_type=ContentType.objects.get_for_model(obj)).delete()
Beispiel #30
0
    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')
            ) | Q(
                related_action_object_content_type=content_type,
                related_action_object_object_id__in=object_ids.filter(
                    actor_only=False).values('object_id')
            )

        return qs.filter(q, **kwargs)
Beispiel #31
0
    def user(self, obj, **kwargs):
        """
        Stream of most recent actions by objects that the passed User obj is
        following.
        """
        q = Q()
        qs = self.public()

        if not obj:
            return qs.none()

        check(obj)
        actors_by_content_type = defaultdict(lambda: [])
        others_by_content_type = defaultdict(lambda: [])

        if kwargs.pop('with_user_activity', False):
            object_content_type = ContentType.objects.get_for_model(obj)
            actors_by_content_type[object_content_type.id].append(obj.pk)

        follow_gfks = get_model('actstream',
                                'follow').objects.filter(user=obj).values_list(
                                    'content_type_id', 'object_id',
                                    'actor_only')

        for content_type_id, object_id, actor_only in follow_gfks.iterator():
            actors_by_content_type[content_type_id].append(object_id)
            if not actor_only:
                others_by_content_type[content_type_id].append(object_id)

        if len(actors_by_content_type) + len(others_by_content_type) == 0:
            return qs.none()

        for content_type_id, object_ids in actors_by_content_type.items():
            q = q | Q(
                actor_content_type=content_type_id,
                actor_object_id__in=object_ids,
            )
        for content_type_id, object_ids in others_by_content_type.items():
            q = q | Q(
                target_content_type=content_type_id,
                target_object_id__in=object_ids,
            ) | Q(
                action_object_content_type=content_type_id,
                action_object_object_id__in=object_ids,
            )
        return qs.filter(q, **kwargs)
    def user(self, obj, **kwargs):
        """
        Stream of most recent actions by objects that the passed User obj is
        following.
        """
        q = Q()
        qs = self.public()

        if not obj:
            return qs.none()

        check(obj)
        actors_by_content_type = defaultdict(lambda: [])
        others_by_content_type = defaultdict(lambda: [])

        if kwargs.pop('with_user_activity', False):
            object_content_type = ContentType.objects.get_for_model(obj)
            actors_by_content_type[object_content_type.id].append(obj.pk)

        follow_gfks = get_model('actstream', 'follow').objects.filter(
            user=obj).values_list('content_type_id',
                                  'object_id', 'actor_only')

        for content_type_id, object_id, actor_only in follow_gfks.iterator():
            actors_by_content_type[content_type_id].append(object_id)
            if not actor_only:
                others_by_content_type[content_type_id].append(object_id)

        if len(actors_by_content_type) + len(others_by_content_type) == 0:
            return qs.none()

        for content_type_id, object_ids in actors_by_content_type.items():
            q = q | Q(
                actor_content_type=content_type_id,
                actor_object_id__in=object_ids,
            )
        for content_type_id, object_ids in others_by_content_type.items():
            q = q | Q(
                target_content_type=content_type_id,
                target_object_id__in=object_ids,
            ) | Q(
                action_object_content_type=content_type_id,
                action_object_object_id__in=object_ids,
            )
        return qs.filter(q, **kwargs)
def unfollow(user, obj, send_action=False):
    """
    Removes a "follow" relationship.

    Set ``send_action`` to ``True`` (``False is default) to also send a
    ``<user> stopped following <object>`` action signal.

    Example::

        unfollow(request.user, other_user)
    """
    check(obj)
    get_model('actstream', 'follow').objects.filter(
        user=user, object_id=obj.pk,
        content_type=ContentType.objects.get_for_model(obj)
    ).delete()
    if send_action:
        action.send(user, verb=_('stopped following'), target=obj)
    def location(self, obj, **kwargs):
        """
        Actstream for location - we try to include also actions related to
        different content types published in this location, eg. comments
        and votes.
        """
        q = Q()
        check(obj)

        if not hasattr(obj, 'published_items'):
            return self.none()

        self_type = ContentType.objects.get_for_model(obj)
        q = q | Q(target_content_type=self_type, target_object_id=obj.pk)

        for ct, id_list in obj.published_items().iteritems():
            q = q | Q(target_content_type=ct, target_object_id__in=id_list)

        return self.filter(q, **kwargs)
    def ngostream(self, obj, **kwargs):
        """
        Activity stream for NGO, presents actions of all memebers.
        """
        q = Q()
        check(obj)

        if not hasattr(obj, 'users'):
            return self.none()

        self_type = ContentType.objects.get_for_model(obj)
        user_type = ContentType.objects.get(app_label="auth", model="user")
        user_list = [int(x.pk) for x in obj.users.all()]

        q = q | Q(target_content_type=self_type, target_object_id=obj.pk)

        q = q | Q(actor_content_type=user_type, actor_object_id__in=user_list)

        return self.filter(q, **kwargs)
Beispiel #36
0
def follow(user, obj, ftype, send_action=True, actor_only=True, **kwargs):
    check(obj)
    instance, created = Follow.objects.get_or_create(
        user=user,
        object_id=obj.pk,
        content_type=ContentType.objects.get_for_model(obj),
        actor_only=actor_only,
        ftype=ftype)

    if send_action and created:
        action.send(user, verb=ftype, target=obj, **kwargs)

    if obj.__class__.__name__ not in RECIPIENT:
        recipient = obj
    else:
        recipient = getattr(obj, RECIPIENT[obj.__class__.__name__], None)

    if recipient and user != recipient:
        notify.send(sender=user, recipient=recipient, verb=ftype, target=obj)
    return instance
Beispiel #37
0
    def mystream(self, obj, **kwargs):
        """
        Custom stream for users. Includes votes and comments info.
        """
        q = Q()
        check(obj)

        objects_by_content_type = defaultdict(lambda: [])

        following = get_model('actstream', 'follow').objects\
            .filter(user=obj).values_list('content_type_id', 'object_id', )
        for content_type_id, object_id in following.iterator():
            objects_by_content_type[content_type_id].append(object_id)

        for content_type_id, object_ids in objects_by_content_type.items():
            q = q | Q(actor_content_type=content_type_id,
                      actor_object_id__in=object_ids, ) | Q(
                          target_content_type=content_type_id,
                          target_object_id__in=object_ids, ) | Q(
                              action_object_content_type=content_type_id,
                              action_object_object_id__in=object_ids, )

        return self.filter(q, **kwargs)
def action_handler(verb, **kwargs):
    """
    Handler function to create Action instance upon action signal call.
    """
    db = kwargs.pop('db', getattr(settings, 'DEFAULT_DB_ALIAS', 'default'))
    kwargs.pop('signal', None)
    actor = kwargs.pop('sender')
    parent_activity = kwargs.pop('parent_activity', None)
    activity_type = kwargs.pop('type', None)

    # 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]

    action_model = apps.get_model('actstream', 'action')
    newaction = action_model(actor_content_type=ContentType.objects.db_manager(
        db).get_for_model(actor),
                             actor_object_id=actor.pk,
                             verb=text_type(verb),
                             public=bool(kwargs.pop('public', True)),
                             description=kwargs.pop('description', None),
                             timestamp=kwargs.pop('timestamp', now()),
                             parent_activity=parent_activity,
                             type=activity_type)

    for opt in ('target', 'action_object', 'permission'):
        obj = kwargs.pop(opt, None)
        if obj is not None:
            check(obj)
            setattr(newaction, '%s_object_id' % opt, obj.pk)
            setattr(newaction, '%s_content_type' % opt,
                    ContentType.objects.db_manager(db).get_for_model(obj))
    if settings.USE_JSONFIELD and len(kwargs):
        newaction.data = kwargs
    newaction.save(force_insert=True, using=db)
    return newaction
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('actstream', '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()
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('actstream', '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()