]> git.openstreetmap.org Git - osqa.git/blobdiff - forum/models/action.py
Merge pull request #2 from udacity/update_django
[osqa.git] / forum / models / action.py
index 1d2e773bb54f882db47356bf64fdf08e45d92597..b3cfd260f33ef8d147e6214245da998f3ac9bd58 100644 (file)
@@ -1,4 +1,6 @@
 from django.utils.translation import ugettext as _
+from django.utils.encoding import smart_unicode
+
 from utils import PickledObjectField
 from threading import Thread
 from forum.utils import html
@@ -15,13 +17,18 @@ class ActionQuerySet(CachedQuerySet):
         else:
             return super(ActionQuerySet, self).obj_from_datadict(datadict)
 
-    def get(self, *args, **kwargs):
-        return super(ActionQuerySet, self).get(*args, **kwargs).leaf()
+    def get(self, *args, **kwargs):            
+        action = super(ActionQuerySet, self).get(*args, **kwargs).leaf
+
+        if not isinstance(action, self.model):
+            raise self.model.DoesNotExist()
+
+        return action
 
 class ActionManager(CachedManager):
     use_for_related_fields = True
 
-    def get_query_set(self):
+    def get_queryset(self):
         qs = ActionQuerySet(self.model)
 
         if self.model is not Action:
@@ -36,9 +43,10 @@ class ActionManager(CachedManager):
 
 class Action(BaseModel):
     user = models.ForeignKey('User', related_name="actions")
-    ip   = models.CharField(max_length=16)
+    real_user = models.ForeignKey('User', related_name="proxied_actions", null=True)
+    ip   = models.CharField(max_length=39)
     node = models.ForeignKey('Node', null=True, related_name="actions")
-    action_type = models.CharField(max_length=16)
+    action_type = models.CharField(max_length=32)
     action_date = models.DateTimeField(default=datetime.datetime.now)
 
     extra = PickledObjectField()
@@ -46,7 +54,7 @@ class Action(BaseModel):
     canceled = models.BooleanField(default=False)
     canceled_by = models.ForeignKey('User', null=True, related_name="canceled_actions")
     canceled_at = models.DateTimeField(null=True)
-    canceled_ip = models.CharField(max_length=16)
+    canceled_ip = models.CharField(max_length=39)
 
     hooks = {}
 
@@ -95,6 +103,7 @@ class Action(BaseModel):
             cancel = ActionRepute(action=self, user=repute.user, value=(-repute.value), by_canceled=True)
             cancel.save()
 
+    @property
     def leaf(self):
         leaf_cls = ActionProxyMetaClass.types.get(self.action_type, None)
 
@@ -111,7 +120,7 @@ class Action(BaseModel):
     def get_type(cls):
         return re.sub(r'action$', '', cls.__name__.lower())
 
-    def save(self, data=None, *args, **kwargs):
+    def save(self, data=None, threaded=True, *args, **kwargs):
         isnew = False
 
         if not self.id:
@@ -127,7 +136,7 @@ class Action(BaseModel):
             if (self.node is None) or (not self.node.nis.wiki):
                 self.repute_users()
             self.process_action()
-            self.trigger_hooks(True)
+            self.trigger_hooks(threaded, True)
 
         return self
 
@@ -145,7 +154,7 @@ class Action(BaseModel):
             self.save()
             self.cancel_reputes()
             self.cancel_action()
-            #self.trigger_hooks(False)
+        #self.trigger_hooks(False)
 
     @classmethod
     def get_current(cls, **kwargs):
@@ -167,15 +176,18 @@ class Action(BaseModel):
 
         Action.hooks[cls].append(fn)
 
-    def trigger_hooks(self, new=True):
-        thread = Thread(target=trigger_hooks_threaded,  args=[self, Action.hooks, new])
-        thread.setDaemon(True)
-        thread.start()
+    def trigger_hooks(self, threaded, new=True):
+        if threaded:
+            thread = Thread(target=trigger_hooks, args=[self, Action.hooks, new])
+            thread.setDaemon(True)
+            thread.start()
+        else:
+            trigger_hooks(self, Action.hooks, new)
 
     class Meta:
         app_label = 'forum'
 
-def trigger_hooks_threaded(action, hooks, new):
+def trigger_hooks(action, hooks, new):
     for cls, hooklist in hooks.items():
         if isinstance(action, cls):
             for hook in hooklist:
@@ -203,13 +215,13 @@ class ActionProxy(Action):
     __metaclass__ = ActionProxyMetaClass
 
     def friendly_username(self, viewer, user):
-        return (viewer == user) and _('You') or user.username
+        return (viewer == user) and _('You') or smart_unicode(user.username)
 
     def friendly_ownername(self, owner, user):
-        return (owner == user) and _('your') or user.username
+        return (owner == user) and _('your') or smart_unicode(user.username)
 
     def viewer_or_user_verb(self, viewer, user, viewer_verb, user_verb):
-        return (viewer == user) and viewer_verb or user_verb    
+        return (viewer == user) and viewer_verb or user_verb
 
     def hyperlink(self, url, title, **attrs):
         return html.hyperlink(url, title, **attrs)
@@ -223,11 +235,14 @@ class ActionProxy(Action):
             node_desc = node_link
 
         return _("%(user)s %(node_name)s %(node_desc)s") % {
-            'user': self.hyperlink(node.author.get_profile_url(), self.friendly_ownername(viewer, node.author)),
-            'node_name': node.friendly_name,
-            'node_desc': node_desc,
+        'user': self.hyperlink(node.author.get_profile_url(), self.friendly_ownername(viewer, node.author)),
+        'node_name': node.friendly_name,
+        'node_desc': node_desc,
         }
-    
+
+    def affected_links(self, viewer):
+        return ", ".join([self.hyperlink(u.get_profile_url(), self.friendly_username(viewer, u)) for u in set([r.user for r in self.reputes.all()])])
+
     class Meta:
         proxy = True
 
@@ -269,7 +284,6 @@ class DummyActionProxy(object):
         cls.hooks.append(fn)
 
 
-
 class ActionRepute(models.Model):
     action = models.ForeignKey(Action, related_name='reputes')
     date = models.DateTimeField(default=datetime.datetime.now)
@@ -287,13 +301,19 @@ class ActionRepute(models.Model):
         if self.value < 0: return self.value
         return 0
 
+    def _add_to_rep(self, value):
+        if int(self.user.reputation + value) < 1 and not settings.ALLOW_NEGATIVE_REPUTATION:
+            return 0
+        else:
+            return models.F('reputation') + value
+
     def save(self, *args, **kwargs):
         super(ActionRepute, self).save(*args, **kwargs)
-        self.user.reputation += self.value
+        self.user.reputation = self._add_to_rep(self.value)
         self.user.save()
 
     def delete(self):
-        self.user.reputation -= self.value
+        self.user.reputation = self._add_to_rep(-self.value)
         self.user.save()
         super(ActionRepute, self).delete()