Follow   A
last analyzed

Size/Duplication

Total Lines 28
Duplicated Lines 0 %

Importance

Changes 3
Bugs 1 Features 0
Metric Value
c 3
b 1
f 0
dl 0
loc 28
rs 10

1 Method

Rating   Name   Duplication   Size   Complexity  
A __str__() 0 2 1
1
from __future__ import unicode_literals
2
3
from django.conf import settings
4
from django.contrib.contenttypes.fields import GenericForeignKey
5
from django.db import models
6
from django.utils.translation import ugettext as _
7
from django.utils.encoding import python_2_unicode_compatible
8
from django.utils.timesince import timesince as djtimesince
9
from django.contrib.contenttypes.models import ContentType
10
11
try:
12
    from django.urls import reverse
13
except ImportError:
14
    from django.core.urlresolvers import reverse
15
16
try:
17
    from django.utils import timezone
18
    now = timezone.now
19
except ImportError:
20
    from datetime import datetime
21
    now = datetime.now
22
23
24
from actstream import settings as actstream_settings
25
from actstream.managers import FollowManager
26
27
now = timezone.now
28
29
30
@python_2_unicode_compatible
31
class Follow(models.Model):
32
    """
33
    Lets a user follow the activities of any specific actor
34
    """
35
    user = models.ForeignKey(
36
        settings.AUTH_USER_MODEL, on_delete=models.CASCADE, db_index=True
37
    )
38
39
    content_type = models.ForeignKey(
40
        ContentType, on_delete=models.CASCADE, db_index=True
41
    )
42
    object_id = models.CharField(max_length=255, db_index=True)
43
    follow_object = GenericForeignKey()
44
    actor_only = models.BooleanField(
45
        "Only follow actions where "
46
        "the object is the target.",
47
        default=True
48
    )
49
    flag = models.CharField(max_length=255, blank=True, db_index=True, default='')
50
    started = models.DateTimeField(default=now, db_index=True)
51
    objects = FollowManager()
52
53
    class Meta:
54
        unique_together = ('user', 'content_type', 'object_id', 'flag')
55
56
    def __str__(self):
57
        return '%s -> %s : %s' % (self.user, self.follow_object, self.flag)
58
59
60
@python_2_unicode_compatible
61
class Action(models.Model):
62
    """
63
    Action model describing the actor acting out a verb (on an optional
64
    target).
65
    Nomenclature based on http://activitystrea.ms/specs/atom/1.0/
66
67
    Generalized Format::
68
69
        <actor> <verb> <time>
70
        <actor> <verb> <target> <time>
71
        <actor> <verb> <action_object> <target> <time>
72
73
    Examples::
74
75
        <justquick> <reached level 60> <1 minute ago>
76
        <brosner> <commented on> <pinax/pinax> <2 hours ago>
77
        <washingtontimes> <started follow> <justquick> <8 minutes ago>
78
        <mitsuhiko> <closed> <issue 70> on <mitsuhiko/flask> <about 2 hours ago>
79
80
    Unicode Representation::
81
82
        justquick reached level 60 1 minute ago
83
        mitsuhiko closed issue 70 on mitsuhiko/flask 3 hours ago
84
85
    HTML Representation::
86
87
        <a href="http://oebfare.com/">brosner</a> commented on <a href="http://github.com/pinax/pinax">pinax/pinax</a> 2 hours ago
88
89
    """
90
    actor_content_type = models.ForeignKey(
91
        ContentType, related_name='actor',
92
        on_delete=models.CASCADE, db_index=True
93
    )
94
    actor_object_id = models.CharField(max_length=255, db_index=True)
95
    actor = GenericForeignKey('actor_content_type', 'actor_object_id')
96
97
    verb = models.CharField(max_length=255, db_index=True)
98
    description = models.TextField(blank=True, null=True)
99
100
    target_content_type = models.ForeignKey(
101
        ContentType, blank=True, null=True,
102
        related_name='target',
103
        on_delete=models.CASCADE, db_index=True
104
    )
105
    target_object_id = models.CharField(
106
        max_length=255, blank=True, null=True, db_index=True
107
    )
108
    target = GenericForeignKey(
109
        'target_content_type',
110
        'target_object_id'
111
    )
112
113
    action_object_content_type = models.ForeignKey(
114
        ContentType, blank=True, null=True,
115
        related_name='action_object',
116
        on_delete=models.CASCADE, db_index=True
117
    )
118
    action_object_object_id = models.CharField(
119
        max_length=255, blank=True, null=True, db_index=True
120
    )
121
    action_object = GenericForeignKey(
122
        'action_object_content_type',
123
        'action_object_object_id'
124
    )
125
126
    timestamp = models.DateTimeField(default=now, db_index=True)
127
128
    public = models.BooleanField(default=True, db_index=True)
129
130
    objects = actstream_settings.get_action_manager()
131
132
    class Meta:
133
        ordering = ('-timestamp',)
134
135
    def __str__(self):
136
        ctx = {
137
            'actor': self.actor,
138
            'verb': self.verb,
139
            'action_object': self.action_object,
140
            'target': self.target,
141
            'timesince': self.timesince()
142
        }
143
        if self.target:
144
            if self.action_object:
145
                return _('%(actor)s %(verb)s %(action_object)s on %(target)s %(timesince)s ago') % ctx
146
            return _('%(actor)s %(verb)s %(target)s %(timesince)s ago') % ctx
147
        if self.action_object:
148
            return _('%(actor)s %(verb)s %(action_object)s %(timesince)s ago') % ctx
149
        return _('%(actor)s %(verb)s %(timesince)s ago') % ctx
150
151
    def actor_url(self):
152
        """
153
        Returns the URL to the ``actstream_actor`` view for the current actor.
154
        """
155
        return reverse('actstream_actor', None,
156
                       (self.actor_content_type.pk, self.actor_object_id))
157
158
    def target_url(self):
159
        """
160
        Returns the URL to the ``actstream_actor`` view for the current target.
161
        """
162
        return reverse('actstream_actor', None,
163
                       (self.target_content_type.pk, self.target_object_id))
164
165
    def action_object_url(self):
166
        """
167
        Returns the URL to the ``actstream_action_object`` view for the current action object
168
        """
169
        return reverse('actstream_actor', None, (
170
            self.action_object_content_type.pk, self.action_object_object_id))
171
172
    def timesince(self, now=None):
173
        """
174
        Shortcut for the ``django.utils.timesince.timesince`` function of the
175
        current timestamp.
176
        """
177
        return djtimesince(self.timestamp, now).encode('utf8').replace(b'\xc2\xa0', b' ').decode('utf8')
178
179
    def get_absolute_url(self):
180
        return reverse(
181
            'actstream.views.detail', [self.pk])
182
183
184
# convenient accessors
185
actor_stream = Action.objects.actor
186
action_object_stream = Action.objects.action_object
187
target_stream = Action.objects.target
188
user_stream = Action.objects.user
189
model_stream = Action.objects.model_actions
190
any_stream = Action.objects.any
191
followers = Follow.objects.followers
192
following = Follow.objects.following
193