• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

justquick / django-activity-stream / 7009540190

27 Nov 2023 06:58PM UTC coverage: 94.394% (-0.6%) from 95.009%
7009540190

Pull #534

github

web-flow
Merge c0f354781 into a7df85e3a
Pull Request #534: Integrated swappable model support

238 of 302 branches covered (0.0%)

99 of 113 new or added lines in 18 files covered. (87.61%)

2 existing lines in 1 file now uncovered.

1549 of 1641 relevant lines covered (94.39%)

11.33 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

73.44
/actstream/actions.py
1
from django.utils.translation import gettext_lazy as _
12✔
2
from django.utils.timezone import now
12✔
3
from django.contrib.contenttypes.models import ContentType
12✔
4
from django.core.exceptions import FieldDoesNotExist
12✔
5

6
from actstream import settings
12✔
7
from actstream.signals import action
12✔
8
from actstream.registry import check
12✔
9

10

11
def follow(user, obj, send_action=True, actor_only=True, flag='', **kwargs):
12✔
12
    """
13
    Creates a relationship allowing the object's activities to appear in the
14
    user's stream.
15

16
    Returns the created ``Follow`` instance.
17

18
    If ``send_action`` is ``True`` (the default) then a
19
    ``<user> started following <object>`` action signal is sent.
20
    Kwargs that can be passed to the Follow model instance will be passed.
21
    Extra keyword arguments are passed to the action.send call.
22

23
    If ``actor_only`` is ``True`` (the default) then only actions where the
24
    object is the actor will appear in the user's activity stream. Set to
25
    ``False`` to also include actions where this object is the action_object or
26
    the target.
27

28
    If ``flag`` not an empty string then the relationship would marked by this flag.
29

30
    Example::
31

32
        follow(request.user, group, actor_only=False)
33
        follow(request.user, group, actor_only=False, flag='liking')
34
    """
35
    check(obj)
12✔
36
    follow_model = settings.get_follow_model()
12✔
37
    instance, created = follow_model.objects.get_or_create(
12✔
38
        user=user, object_id=obj.pk, flag=flag,
39
        content_type=ContentType.objects.get_for_model(obj),
40
        actor_only=actor_only
41
    )
42
    follow_updated = False
12✔
43
    for attr in list(kwargs):
12✔
44
        try:
12✔
45
            follow_model._meta.get_field(attr)
12✔
46
        except FieldDoesNotExist:
12✔
47
            pass
12✔
48
        else:
NEW
49
            follow_updated = True
×
NEW
50
            setattr(instance, attr, kwargs.pop(attr))
×
51
    if follow_updated:
12!
NEW
52
        instance.save()
×
53
    if send_action and created:
12✔
54
        if not flag:
12✔
55
            action.send(user, verb=_('started following'), target=obj, **kwargs)
12✔
56
        else:
57
            action.send(user, verb=_('started %s' % flag), target=obj, **kwargs)
12✔
58
    return instance
12✔
59

60

61
def unfollow(user, obj, send_action=False, flag=''):
12✔
62
    """
63
    Removes a "follow" relationship.
64

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

68
    Pass a string value to ``flag`` to determine which type of "follow" relationship you want to remove.
69

70
    Example::
71

72
        unfollow(request.user, other_user)
73
        unfollow(request.user, other_user, flag='watching')
74
    """
75
    check(obj)
12✔
76
    qs = settings.get_follow_model().objects.filter(
12✔
77
        user=user, object_id=obj.pk,
78
        content_type=ContentType.objects.get_for_model(obj)
79
    )
80

81
    if flag:
12✔
82
        qs = qs.filter(flag=flag)
12✔
83
    qs.delete()
12✔
84

85
    if send_action:
12!
86
        if not flag:
×
87
            action.send(user, verb=_('stopped following'), target=obj)
×
88
        else:
89
            action.send(user, verb=_('stopped %s' % flag), target=obj)
×
90

91

92
def is_following(user, obj, flag=''):
12✔
93
    """
94
    Checks if a "follow" relationship exists.
95

96
    Returns True if exists, False otherwise.
97

98
    Pass a string value to ``flag`` to determine which type of "follow" relationship you want to check.
99

100
    Example::
101

102
        is_following(request.user, group)
103
        is_following(request.user, group, flag='liking')
104
    """
105
    check(obj)
×
106

NEW
107
    qs = settings.get_follow_model().objects.filter(
×
108
        user=user, object_id=obj.pk,
109
        content_type=ContentType.objects.get_for_model(obj)
110
    )
111

112
    if flag:
×
113
        qs = qs.filter(flag=flag)
×
114

115
    return qs.exists()
×
116

117

118
def action_handler(verb, **kwargs):
12✔
119
    """
120
    Handler function to create Action instance upon action signal call.
121
    Extra kwargs will be passed to the Action instance
122
    """
123
    kwargs.pop('signal', None)
12✔
124
    actor = kwargs.pop('sender')
12✔
125

126
    # We must store the untranslated string
127
    # If verb is an ugettext_lazyed string, fetch the original string
128
    if hasattr(verb, '_proxy____args'):
12✔
129
        verb = verb._proxy____args[0]
12✔
130

131
    newaction = settings.get_action_model()(
12✔
132
        actor_content_type=ContentType.objects.get_for_model(actor),
133
        actor_object_id=actor.pk,
134
        verb=str(verb),
135
        public=bool(kwargs.pop('public', True)),
136
        description=kwargs.pop('description', None),
137
        timestamp=kwargs.pop('timestamp', now())
138
    )
139

140
    for opt in ('target', 'action_object'):
12✔
141
        obj = kwargs.pop(opt, None)
12✔
142
        if obj is not None:
12✔
143
            check(obj)
12✔
144
            setattr(newaction, '%s_object_id' % opt, obj.pk)
12✔
145
            setattr(newaction, '%s_content_type' % opt,
12✔
146
                    ContentType.objects.get_for_model(obj))
147
    for attr in list(kwargs):
12!
NEW
148
        try:
×
NEW
UNCOV
149
            settings.get_action_model()._meta.get_field(attr)
×
NEW
UNCOV
150
        except FieldDoesNotExist:
×
NEW
151
            pass
×
152
        else:
NEW
153
            setattr(newaction, attr, kwargs.pop(attr))
×
154
    if settings.USE_JSONFIELD and len(kwargs):
12!
155
        newaction.data = kwargs
×
156
    newaction.save(force_insert=True)
12✔
157
    return newaction
12✔
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc