author = models.ForeignKey(User, related_name='%(class)ss')\r
body = models.TextField()\r
\r
+ @property\r
+ def user(self):\r
+ return self.author\r
+\r
@property\r
def html(self):\r
return mark_safe(sanitize_html(markdown.markdown(self.body)))\r
def headline(self):\r
return self.title\r
\r
- @property\r
- def summary(self):\r
- return strip_tags(self.html)[:300]\r
-\r
def tagname_list(self):\r
if self.tagnames:\r
return [name for name in self.tagnames.split(u' ')]\r
name = node_cls.__name__.lower()\r
\r
def children(self):\r
- return node_cls.objects.filter(parent=self)\r
+ if node_cls._meta.proxy:\r
+ return node_cls.objects.filter(node_type=name, parent=self)\r
+ else:\r
+ return node_cls.objects.filter(parent=self)\r
\r
def parent(self):\r
p = self.__dict__.get('_%s_cache' % name, None)\r
\r
- if p is None:\r
- try:\r
- p = self.parent.leaf\r
- self.__dict__['_%s_cache' % name] = p\r
- except Exception, e:\r
- pass\r
+ if p is None and (self.parent is not None) and self.parent.node_type == name:\r
+ p = self.parent.leaf\r
+ self.__dict__['_%s_cache' % name] = p\r
\r
return p\r
\r
Node.add_to_class(name, property(parent))\r
\r
\r
+node_create = django.dispatch.Signal(providing_args=['instance'])\r
+node_edit = django.dispatch.Signal(providing_args=['instance'])\r
+\r
class Node(BaseModel, NodeContent, DeletableContent):\r
__metaclass__ = NodeMetaClass\r
\r
node_type = models.CharField(max_length=16, default='node')\r
parent = models.ForeignKey('Node', related_name='children', null=True)\r
+ abs_parent = models.ForeignKey('Node', related_name='all_children', null=True)\r
\r
added_at = models.DateTimeField(default=datetime.datetime.now)\r
\r
tags = models.ManyToManyField('Tag', related_name='%(class)ss')\r
\r
- score = models.IntegerField(default=0)\r
- vote_up_count = models.IntegerField(default=0)\r
+ score = DenormalizedField(default=0)\r
+ vote_up_count = DenormalizedField(default=0)\r
vote_down_count = models.IntegerField(default=0)\r
\r
- comment_count = models.PositiveIntegerField(default=0)\r
- offensive_flag_count = models.SmallIntegerField(default=0)\r
+ comment_count = DenormalizedField(default=0)\r
+ offensive_flag_count = DenormalizedField(default=0)\r
\r
last_edited_at = models.DateTimeField(null=True, blank=True)\r
last_edited_by = models.ForeignKey(User, null=True, blank=True, related_name='last_edited_%(class)ss')\r
def leaf(self):\r
return NodeMetaClass.types[self.node_type].objects.get(id=self.id)\r
\r
+ @property \r
+ def absolute_parent(self):\r
+ if not self.abs_parent_id:\r
+ return self.leaf\r
+\r
+ return self.abs_parent.leaf\r
+\r
+ @property\r
+ def summary(self):\r
+ return strip_tags(self.html)[:300]\r
+\r
def create_revision(self, user, **kwargs):\r
revision = NodeRevision(author=user, **kwargs)\r
\r
self.title = revision.title\r
self.tagnames = revision.tagnames\r
self.body = revision.body\r
- \r
- self.last_edited_at = datetime.datetime.now()\r
- self.last_edited_by = user\r
\r
+ old_revision = self.active_revision\r
self.active_revision = revision\r
+\r
+ if not old_revision:\r
+ signal = node_create\r
+ else:\r
+ self.last_edited_at = datetime.datetime.now()\r
+ self.last_edited_by = user\r
+ signal = node_edit\r
+\r
self.save()\r
+ signal.send(sender=self.__class__, instance=self)\r
\r
def get_tag_list_if_changed(self):\r
dirty = self.get_dirty_fields()\r
def save(self, *args, **kwargs):\r
if not self.id:\r
self.node_type = self.__class__.__name__.lower()\r
+\r
+ if self.parent_id and not self.abs_parent_id:\r
+ self.abs_parent = self.parent.absolute_parent\r
+\r
+ self.__dict__['score'] = self.__dict__['vote_up_count'] - self.__dict__['vote_down_count']\r
\r
tags = self.get_tag_list_if_changed()\r
super(Node, self).save(*args, **kwargs)\r
app_label = 'forum'\r
\r
\r
-class NodeRevision(NodeContent):\r
+class NodeRevision(BaseModel, NodeContent):\r
node = models.ForeignKey(Node, related_name='revisions')\r
summary = models.CharField(max_length=300)\r
revision = models.PositiveIntegerField()\r