예제 #1
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, 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
예제 #2
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 = 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
예제 #3
0
def setup_generic_relations(model_class):
    """
    Set up GenericRelations for actionable models.
    """
    Action = get_model('actstream', 'action')

    if Action is None:
        raise RegistrationError(
            'Unable get actstream.Action. Potential circular imports '
            'in initialisation. Try moving actstream app to come after the '
            'apps which have models to register in the INSTALLED_APPS setting.'
        )

    related_attr_name = 'related_name'
    related_attr_value = 'actions_with_%s' % label(model_class)
    if django.VERSION[:2] >= (1, 7):
        related_attr_name = 'related_query_name'
    relations = {}
    for field in ('actor', 'target', 'action_object'):
        attr = '%s_actions' % field
        attr_value = '%s_as_%s' % (related_attr_value, field)
        kwargs = {
            'content_type_field': '%s_content_type' % field,
            'object_id_field': '%s_object_id' % field,
            related_attr_name: attr_value
        }
        rel = generic.GenericRelation('actstream.Action', **kwargs)
        rel.contribute_to_class(model_class, attr)
        relations[field] = rel

        # @@@ I'm not entirely sure why this works
        setattr(Action, attr_value, None)
    return relations
예제 #4
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 = 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):
        if not settings.USE_POSTGRES:
            newaction.data = json.dumps(kwargs)
        else:
            newaction.data = kwargs
    newaction.save(force_insert=True)
    return newaction
예제 #5
0
def setup_generic_relations(model_class):
    """
    Set up GenericRelations for actionable models.
    """
    Action = get_model('actstream', 'action')

    if Action is None:
        raise RegistrationError('Unable get actstream.Action. Potential circular imports '
                                'in initialisation. Try moving actstream app to come after the '
                                'apps which have models to register in the INSTALLED_APPS setting.')

    related_attr_name = 'related_name'
    related_attr_value = 'actions_with_%s' % label(model_class)
    if django.VERSION[:2] >= (1, 7):
        related_attr_name = 'related_query_name'
    relations = {}
    for field in ('actor', 'target', 'action_object'):
        attr = '%s_actions' % field
        attr_value = '%s_as_%s' % (related_attr_value, field)
        kwargs = {
            'content_type_field': '%s_content_type' % field,
            'object_id_field': '%s_object_id' % field,
            related_attr_name: attr_value
        }
        rel = generic.GenericRelation('actstream.Action', **kwargs)
        rel = rel.contribute_to_class(model_class, attr)
        relations[field] = rel

        # @@@ I'm not entirely sure why this works
        setattr(Action, attr_value, None)
    return relations
예제 #6
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,
        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
예제 #7
0
 def tearDown(self):
     for model in self.actstream_models:
         model = get_model(*model.split('.'))
         unregister(model)
         model.objects.all().delete()
     Action.objects.all().delete()
     Follow.objects.all().delete()
     self.User.objects.all().delete()
예제 #8
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, object_id=obj.pk,
        content_type=ContentType.objects.get_for_model(obj)
    ).delete()
    if send_action:
        action.send(user, verb=_('stopped following'), target=obj)
예제 #9
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,
        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 validate(model_class, exception_class=ImproperlyConfigured):
    if isinstance(model_class, string_types):
        model_class = get_model(*model_class.split('.'))
    if not isinstance(model_class, ModelBase):
        raise exception_class(
            'Object %r is not a Model class.' % model_class)
    if model_class._meta.abstract:
        raise exception_class(
            'The model %r is abstract, so it cannot be registered with '
            'actstream.' % model_class)
    return model_class
예제 #11
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 get_model('actstream', 'follow').objects.filter(
        user=user, object_id=obj.pk,
        content_type=ContentType.objects.get_for_model(obj)
    ).exists()
예제 #12
0
def validate(model_class, exception_class=ImproperlyConfigured):
    if isinstance(model_class, string_types):
        model_class = get_model(*model_class.split('.'))
    if not isinstance(model_class, ModelBase):
        raise exception_class('Object %r is not a Model class.' % model_class)
    if model_class._meta.abstract:
        raise exception_class(
            'The model %r is abstract, so it cannot be registered with '
            'actstream.' % model_class)
    if not is_installed(model_class):
        raise exception_class(
            'The model %r is not installed, please put the app "%s" in your '
            'INSTALLED_APPS setting.' %
            (model_class, model_class._meta.app_label))
    return model_class
예제 #13
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 get_model('actstream', 'follow').objects.filter(
        user=user,
        object_id=obj.pk,
        content_type=ContentType.objects.get_for_model(obj)).exists()
예제 #14
0
def validate(model_class, exception_class=ImproperlyConfigured):
    if isinstance(model_class, string_types):
        model_class = get_model(*model_class.split('.'))
    if not isinstance(model_class, ModelBase):
        raise exception_class(
            'Object %r is not a Model class.' % model_class)
    if model_class._meta.abstract:
        raise exception_class(
            'The model %r is abstract, so it cannot be registered with '
            'actstream.' % model_class)
    if not is_installed(model_class):
        raise exception_class(
            'The model %r is not installed, please put the app "%s" in your '
            'INSTALLED_APPS setting.' % (model_class,
                                         model_class._meta.app_label))
    return model_class
예제 #15
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)
예제 #16
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)