1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
|
from django.db import models
from askbot.utils import markup
from askbot.utils.html import sanitize_html
#class Post(models.Model):
# pass
class PostRevisionManager(models.Manager):
def create_question_revision(self, *kargs, **kwargs):
kwargs['revision_type'] = self.model.QUESTION_REVISION
return self.create(*kargs, **kwargs)
def create_answer_revision(self, *kargs, **kwargs):
kwargs['revision_type'] = self.model.ANSWER_REVISION
return self.create(*kargs, **kwargs)
def question_revisions(self):
return self.filter(revision_type=self.model.QUESTION_REVISION)
def answer_revisions(self):
return self.filter(revision_type=self.model.ANSWER_REVISION)
class PostRevision(models.Model):
QUESTION_REVISION_TEMPLATE_NO_TAGS = (
'<h3>%(title)s</h3>\n'
'<div class="text">%(html)s</div>\n'
)
QUESTION_REVISION = 1
ANSWER_REVISION = 2
REVISION_TYPE_CHOICES = (
(QUESTION_REVISION, 'question'),
(ANSWER_REVISION, 'answer'),
)
REVISION_TYPE_CHOICES_DICT = dict(REVISION_TYPE_CHOICES)
answer = models.ForeignKey('askbot.Answer', related_name='revisions', null=True, blank=True)
question = models.ForeignKey('askbot.Question', related_name='revisions', null=True, blank=True)
revision_type = models.SmallIntegerField(choices=REVISION_TYPE_CHOICES)
revision = models.PositiveIntegerField()
author = models.ForeignKey('auth.User', related_name='%(class)ss')
revised_at = models.DateTimeField()
summary = models.CharField(max_length=300, blank=True)
text = models.TextField()
# Question-specific fields
title = models.CharField(max_length=300, blank=True, default='')
tagnames = models.CharField(max_length=125, blank=True, default='')
is_anonymous = models.BooleanField(default=False)
objects = PostRevisionManager()
class Meta:
# INFO: This `unique_together` constraint might be problematic for databases in which
# 2+ NULLs cannot be stored in an UNIQUE column.
# As far as I know MySQL, PostgreSQL and SQLite allow that so we're on the safe side.
unique_together = (('answer', 'revision'), ('question', 'revision'))
ordering = ('-revision',)
app_label = 'askbot'
def revision_type_str(self):
return self.REVISION_TYPE_CHOICES_DICT[self.revision_type]
def __unicode__(self):
return u'%s - revision %s of %s' % (self.revision_type_str(), self.revision, self.title)
def parent(self):
if self.is_question_revision():
return self.question
elif self.is_answer_revision():
return self.answer
def save(self, **kwargs):
"""Determines the revistion type and then looks up the next available revision number if not set."""
if not self.revision:
# TODO: Maybe use Max() aggregation?
# TODO: Handle IntegrityError if revision id is already occupied?
self.revision = self.parent().revisions.values_list('revision', flat=True)[0] + 1
self.full_clean() # Make sure that everything is ok, in particular that `revision_type` and `revision` are set to valid values
super(PostRevision, self).save(**kwargs)
def is_question_revision(self):
return self.revision_type == self.QUESTION_REVISION
def is_answer_revision(self):
return self.revision_type == self.ANSWER_REVISION
@models.permalink
def get_absolute_url(self):
if self.is_question_revision():
return 'question_revisions', (self.question.id,), {}
elif self.is_answer_revision():
return 'answer_revisions', (), {'id':self.answer.id}
def get_question_title(self):
#INFO: ack-grepping shows that it's only used for Questions, so there's no code for Answers
return self.question.title
def as_html(self, **kwargs):
markdowner = markup.get_parser()
sanitized_html = sanitize_html(markdowner.convert(self.text))
if self.is_question_revision():
return self.QUESTION_REVISION_TEMPLATE_NO_TAGS % {
'title': self.title,
'html': sanitized_html
}
elif self.is_answer_revision():
return sanitized_html
|