The first comment's indent level is 0.
The comments must be a complete subtree, ordered by their `left` property.
+
+ This function will also cache the `parent` property for each comment.
"""
last_comment = None
- indent = 0
+ indent = 0
right_ancestry = []
for comment in comments:
# If this comment is a child of the last, bump the nesting level
if last_comment and comment.left < last_comment.right:
- indent = indent + 1
+ indent = indent + 1
# Remember current ancestory relevant to the root
right_ancestry.append(last_comment)
# broken out of, back out a level
for i in xrange(len(right_ancestry) - 1, -1, -1):
if comment.left > right_ancestry[i].right:
- indent = indent - 1
+ indent = indent - 1
right_ancestry.pop(i)
# Cache parent comment
comments = OneToMany('Comment', order_by='left')
class Comment(Entity):
- time = Field(DateTime, default=datetime.datetime.now)
- text = Field(Unicode(65536))
+ time = Field(DateTime, default=datetime.datetime.now, required=True)
+ text = Field(Unicode(65536), required=True)
# Comments are a tree, and are stored as a nested set, because:
# - It's easy to get a subtree with a single query.
# The only real disadvantage is that adding a comment requires a quick
# update of all the following comments (in post-order), but that's rare
# enough that it shouldn't be a problem.
- left = Field(Integer, index=True)
- right = Field(Integer)
+ left = Field(Integer, index=True, required=True)
+ right = Field(Integer, required=True)
- discussion = ManyToOne('Discussion')
- user = ManyToOne('User')
+ discussion = ManyToOne('Discussion', required=True)
+ user = ManyToOne('User', required=True)
def __init__(self, parent=None, **kwargs):
"""Constructor override to set left/right correctly on a new comment.
# comment's left/right
Comment.query.filter(Comment.discussion == self.discussion) \
.filter(Comment.left >= parent_right) \
- .update({ Comment.left: Comment.left + 2 })
+ .update({ 'left': Comment.left + 2 })
Comment.query.filter(Comment.discussion == self.discussion) \
.filter(Comment.right >= parent_right) \
- .update({ Comment.right: Comment.right + 2 })
+ .update({ 'right': Comment.right + 2 })
# Then stick the new comment in the right place
self.left = parent_right
self.left = max_right + 1
self.right = max_right + 2
+ @property
+ def parent(self):
+ """Returns this comment's parent. This is cached, hence its being a
+ property and not a method.
+ """
+ if not hasattr(self, '_parent'):
+ self._parent = Comment.query \
+ .filter(Comment.discussion_id == self.discussion_id) \
+ .filter(Comment.left < self.left) \
+ .filter(Comment.right > self.right) \
+ .order_by(Comment.left.desc()) \
+ .first()
+ return self._parent