]> git.openstreetmap.org Git - osqa.git/blobdiff - forum/models/node.py
Added the option to limit the tags creation. It will defaults to false, and there...
[osqa.git] / forum / models / node.py
index 6f4e12b0429823bb4abad4d6243e18356e882c33..b375ec44c1d1dc21fdfa9f67ac22761b90631da4 100644 (file)
@@ -1,4 +1,5 @@
 from base import *\r
+import re\r
 from tag import Tag\r
 \r
 import markdown\r
@@ -79,13 +80,21 @@ class NodeMetaClass(BaseMetaClass):
 \r
 \r
 class NodeQuerySet(CachedQuerySet):\r
+    def obj_from_datadict(self, datadict):\r
+        cls = NodeMetaClass.types.get(datadict.get("node_type", ""), None)\r
+        if cls:\r
+            obj = cls()\r
+            obj.__dict__.update(datadict)\r
+            return obj\r
+        else:\r
+            return super(NodeQuerySet, self).obj_from_datadict(datadict)\r
+\r
     def get(self, *args, **kwargs):\r
-        node = super(NodeQuerySet, self).get(*args, **kwargs)\r
-        cls = NodeMetaClass.types.get(node.node_type, None)\r
+        return super(NodeQuerySet, self).get(*args, **kwargs).leaf\r
 \r
-        if cls and (node.__class__ is not cls):\r
-            return node.leaf\r
-        return node\r
+    def filter_state(self, **kwargs):\r
+        apply_bool = lambda q, b: b and q or ~q\r
+        return self.filter(*[apply_bool(models.Q(state_string__contains="(%s)" % s), b) for s, b in kwargs.items()])\r
 \r
 \r
 class NodeManager(CachedManager):\r
@@ -103,6 +112,60 @@ class NodeManager(CachedManager):
         kwargs['node_type__in'] = [t.get_type() for t in types]\r
         return self.get(*args, **kwargs)\r
 \r
+    def filter_state(self, **kwargs):\r
+        return self.all().filter_state(**kwargs)\r
+\r
+\r
+class NodeStateDict(object):\r
+    def __init__(self, node):\r
+        self.__dict__['_node'] = node\r
+\r
+    def __getattr__(self, name):\r
+        if self.__dict__.get(name, None):\r
+            return self.__dict__[name]\r
+\r
+        try:\r
+            node = self.__dict__['_node']\r
+            action = NodeState.objects.get(node=node, state_type=name).action\r
+            self.__dict__[name] = action\r
+            return action\r
+        except:\r
+            return None\r
+\r
+    def __setattr__(self, name, value):\r
+        current = self.__getattr__(name)\r
+\r
+        if value:\r
+            if current:\r
+                current.action = value\r
+                current.save()\r
+            else:\r
+                node = self.__dict__['_node']\r
+                state = NodeState(node=node, action=value, state_type=name)\r
+                state.save()\r
+                self.__dict__[name] = value\r
+\r
+                if not "(%s)" % name in node.state_string:\r
+                    node.state_string = "%s(%s)" % (node.state_string, name)\r
+                    node.save()\r
+        else:\r
+            if current:\r
+                node = self.__dict__['_node']\r
+                node.state_string = "".join("(%s)" % s for s in re.findall('\w+', node.state_string) if s != name)\r
+                node.save()\r
+                current.node_state.delete()\r
+                del self.__dict__[name]\r
+\r
+\r
+class NodeStateQuery(object):\r
+    def __init__(self, node):\r
+        self.__dict__['_node'] = node\r
+\r
+    def __getattr__(self, name):\r
+        node = self.__dict__['_node']\r
+        return "(%s)" % name in node.state_string\r
+\r
+\r
 \r
 class Node(BaseModel, NodeContent):\r
     __metaclass__ = NodeMetaClass\r
@@ -114,8 +177,7 @@ class Node(BaseModel, NodeContent):
     added_at             = models.DateTimeField(default=datetime.datetime.now)\r
     score                 = models.IntegerField(default=0)\r
 \r
-    deleted               = models.ForeignKey('Action', null=True, unique=True, related_name="deleted_node")\r
-    in_moderation         = models.ForeignKey('Action', null=True, unique=True, related_name="moderated_node")\r
+    state_string          = models.TextField(default='')\r
     last_edited           = models.ForeignKey('Action', null=True, unique=True, related_name="edited_node")\r
 \r
     last_activity_by       = models.ForeignKey(User, null=True)\r
@@ -126,10 +188,8 @@ class Node(BaseModel, NodeContent):
 \r
     extra_ref = models.ForeignKey('Node', null=True)\r
     extra_count = models.IntegerField(default=0)\r
-    extra_action = models.ForeignKey('Action', null=True, related_name="extra_node")\r
-    \r
+\r
     marked = models.BooleanField(default=False)\r
-    wiki = models.BooleanField(default=False)\r
 \r
     comment_count = DenormalizedField("children", node_type="comment", canceled=False)\r
     flag_count = DenormalizedField("flags")\r
@@ -140,7 +200,7 @@ class Node(BaseModel, NodeContent):
 \r
     @classmethod\r
     def cache_key(cls, pk):\r
-        return '%s.node:%s' % (settings.APP_URL, pk)\r
+        return '%s:node:%s' % (settings.APP_URL, pk)\r
 \r
     @classmethod\r
     def get_type(cls):\r
@@ -157,12 +217,36 @@ class Node(BaseModel, NodeContent):
         leaf.__dict__ = self.__dict__\r
         return leaf\r
 \r
+    @property\r
+    def nstate(self):\r
+        state = self.__dict__.get('_nstate', None)\r
+\r
+        if state is None:\r
+            state = NodeStateDict(self)\r
+            self._nstate = state\r
+\r
+        return state\r
+\r
+    @property\r
+    def nis(self):\r
+        nis = self.__dict__.get('_nis', None)\r
+\r
+        if nis is None:\r
+            nis = NodeStateQuery(self)\r
+            self._nis = nis\r
+\r
+        return nis\r
+\r
+    @property\r
+    def deleted(self):\r
+        return self.nis.deleted\r
+\r
     @property    \r
     def absolute_parent(self):\r
         if not self.abs_parent_id:\r
-            return self.leaf\r
+            return self\r
 \r
-        return self.abs_parent.leaf\r
+        return self.abs_parent\r
 \r
     @property\r
     def summary(self):\r
@@ -209,8 +293,8 @@ class Node(BaseModel, NodeContent):
         if not 'tagnames' in dirty:\r
             return None\r
         else:\r
-            if dirty['tagnames']:\r
-                old_tags = set(name for name in dirty['tagnames'].split(u' '))\r
+            if self._original_state['tagnames']:\r
+                old_tags = set(name for name in self._original_state['tagnames'].split(u' '))\r
             else:\r
                 old_tags = set()\r
             new_tags = set(name for name in self.tagnames.split(u' ') if name)\r
@@ -234,18 +318,16 @@ class Node(BaseModel, NodeContent):
                 except:\r
                     tag = Tag.objects.create(name=name, created_by=self._last_active_user())\r
 \r
-                if not self.deleted:\r
+                if not self.nis.deleted:\r
                     tag.used_count = models.F('used_count') + 1\r
                     tag.save()\r
 \r
-            if not self.deleted:\r
+            if not self.nis.deleted:\r
                 for name in tag_changes['removed']:\r
                     try:\r
                         tag = Tag.objects.get(name=name)\r
                         tag.used_count = models.F('used_count') - 1\r
                         tag.save()\r
-                        if tag.used_count == 0:\r
-                            tag.mark_deleted(self._last_active_user())\r
                     except:\r
                         pass\r
 \r
@@ -254,21 +336,21 @@ class Node(BaseModel, NodeContent):
         return False\r
 \r
     def mark_deleted(self, action):\r
-        self.deleted = action\r
+        self.nstate.deleted = action\r
         self.save()\r
 \r
         if action:\r
             for tag in self.tags.all():\r
                 tag.used_count = models.F('used_count') - 1\r
                 tag.save()\r
-                if tag.used_count == 0:\r
-                    tag.mark_deleted(self._last_active_user())\r
         else:\r
             for tag in Tag.objects.filter(name__in=self.tagname_list()):\r
                 tag.used_count = models.F('used_count') + 1\r
                 tag.save()\r
 \r
     def save(self, *args, **kwargs):\r
+        tags_changed = self._process_changes_in_tags()\r
+        \r
         if not self.id:\r
             self.node_type = self.get_type()\r
             super(BaseModel, self).save(*args, **kwargs)\r
@@ -278,8 +360,6 @@ class Node(BaseModel, NodeContent):
         if self.parent_id and not self.abs_parent_id:\r
             self.abs_parent = self.parent.absolute_parent\r
 \r
-        tags_changed = self._process_changes_in_tags()\r
-\r
         super(Node, self).save(*args, **kwargs)\r
         if tags_changed: self.tags = list(Tag.objects.filter(name__in=self.tagname_list()))\r
 \r
@@ -298,3 +378,13 @@ class NodeRevision(BaseModel, NodeContent):
         app_label = 'forum'\r
 \r
 \r
+class NodeState(models.Model):\r
+    node       = models.ForeignKey(Node, related_name='states')\r
+    state_type = models.CharField(max_length=16)\r
+    action     = models.OneToOneField('Action', related_name="node_state")\r
+\r
+    class Meta:\r
+        unique_together = ('node', 'state_type')\r
+        app_label = 'forum'\r
+\r
+\r