reply.py 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197
  1. from django.db.models import F
  2. from django.utils.translation import ugettext_lazy as _, ungettext
  3. from misago.conf import settings
  4. from misago.core import forms
  5. from misago.core.validators import validate_sluggable
  6. from misago.markup import Editor, common_flavour
  7. from misago.threads.checksums import update_post_checksum
  8. from misago.threads.forms.posting import (EditorFormsetMiddleware,
  9. START, REPLY, EDIT)
  10. class ReplyForm(forms.Form):
  11. is_main = True
  12. legend = _("Reply")
  13. template = "misago/threads/replyform.html"
  14. js_template = "misago/threads/replyform_js.html"
  15. post = forms.CharField(label=_("Message body"), required=False)
  16. def __init__(self, post=None, *args, **kwargs):
  17. self.post_instance = post
  18. self.parsing_result = {}
  19. super(ReplyForm, self).__init__(*args, **kwargs)
  20. def validate_post(self, post):
  21. post_len = len(post)
  22. if not post_len:
  23. raise forms.ValidationError(_("Enter message."))
  24. if post_len < settings.post_length_min:
  25. message = ungettext(
  26. "Posted message should be at least %(limit)s character long.",
  27. "Posted message should be at least %(limit)s characters long.",
  28. settings.post_length_min)
  29. message = message % {'limit': settings.post_length_min}
  30. raise forms.ValidationError(message)
  31. if settings.post_length_max and post_len > settings.post_length_max:
  32. message = ungettext(
  33. "Posted message can't be longer than %(limit)s character.",
  34. "Posted message can't be longer than %(limit)s characters.",
  35. settings.post_length_max,)
  36. message = message % {'limit': settings.post_length_max}
  37. raise forms.ValidationError(message)
  38. self.parsing_result = common_flavour(post, self.post_instance.poster)
  39. self.post_instance.post = self.parsing_result['original_text']
  40. self.post_instance.post_parsed = self.parsing_result['parsed_text']
  41. def validate_data(self, data):
  42. self.validate_post(data.get('post', ''))
  43. def clean(self):
  44. data = super(ReplyForm, self).clean()
  45. self.validate_data(data)
  46. return data
  47. class ThreadForm(ReplyForm):
  48. legend = _("Thread ")
  49. title = forms.CharField(label=_("Thread title"), required=False)
  50. def __init__(self, thread=None, *args, **kwargs):
  51. self.thread_instance = thread
  52. super(ThreadForm, self).__init__(*args, **kwargs)
  53. def validate_title(self, title):
  54. title_len = len(title)
  55. if not title_len:
  56. raise forms.ValidationError(_("Enter thread title."))
  57. if title_len < settings.thread_title_length_min:
  58. message = ungettext(
  59. "Thread title should be at least %(limit)s character long.",
  60. "Thread title should be at least %(limit)s characters long.",
  61. settings.thread_title_length_min)
  62. message = message % {'limit': settings.thread_title_length_min}
  63. raise forms.ValidationError(message)
  64. if title_len > settings.thread_title_length_max:
  65. message = ungettext(
  66. "Thread title can't be longer than %(limit)s character.",
  67. "Thread title can't be longer than %(limit)s characters.",
  68. settings.thread_title_length_max,)
  69. message = message % {'limit': settings.thread_title_length_max}
  70. raise forms.ValidationError(message)
  71. error_not_sluggable = _("Thread title should contain "
  72. "alpha-numeric characters.")
  73. error_slug_too_long = _("Thread title is too long.")
  74. slug_validator = validate_sluggable(error_not_sluggable,
  75. error_slug_too_long)
  76. slug_validator(title)
  77. def validate_data(self, data):
  78. errors = []
  79. if not data.get('title') and not data.get('post'):
  80. raise forms.ValidationError(_("Enter thread title and message."))
  81. try:
  82. self.validate_title(data.get('title', ''))
  83. except forms.ValidationError as e:
  84. errors.append(e)
  85. try:
  86. self.validate_post(data.get('post', ''))
  87. except forms.ValidationError as e:
  88. errors.append(e)
  89. if errors:
  90. raise forms.ValidationError(errors)
  91. class PrefixedThreadForm(ThreadForm):
  92. pass
  93. class ReplyFormMiddleware(EditorFormsetMiddleware):
  94. def make_form(self):
  95. initial_data = {'title': self.thread.title, 'post': self.post.post}
  96. if self.mode == START:
  97. if self.request.method == 'POST':
  98. form = ThreadForm(self.thread, self.post, self.request.POST)
  99. else:
  100. form = ThreadForm(self.thread, self.post, initial=initial_data)
  101. else:
  102. if self.request.method == 'POST':
  103. form = ReplyForm(self.post, self.request.POST)
  104. else:
  105. form = ReplyForm(self.post, initial=initial_data)
  106. form.post_editor = Editor(form['post'])
  107. return form
  108. def pre_save(self, form):
  109. self.parsing_result.update(form.parsing_result)
  110. def save(self, form):
  111. # if we are starting new thread, create empty model
  112. if self.mode == START:
  113. self.thread.set_title(form.cleaned_data['title'])
  114. self.thread.starter_name = '-'
  115. self.thread.starter_slug = '-'
  116. self.thread.last_poster_name = '-'
  117. self.thread.last_poster_slug = '-'
  118. self.thread.started_on = self.datetime
  119. self.thread.last_post_on = self.datetime
  120. self.thread.save()
  121. # make changes/set data on post
  122. self.post.updated_on = self.datetime
  123. if self.mode == EDIT:
  124. self.post.last_editor_name = self.user
  125. self.post.poster_name = self.user.username
  126. self.post.poster_slug = self.user.slug
  127. else:
  128. self.post.thread = self.thread
  129. self.post.poster = self.user
  130. self.post.poster_name = self.user.username
  131. self.post.poster_ip = self.request._misago_real_ip
  132. self.post.posted_on = self.datetime
  133. self.post.post_checksum = update_post_checksum(self.post)
  134. self.post.save()
  135. # Update thread
  136. if self.mode == START:
  137. self.forum.threads += 1
  138. self.thread.set_first_post(self.post)
  139. if self.mode != EDIT:
  140. self.thread.set_last_post(self.post)
  141. if self.mode != REPLY:
  142. self.thread.replies += 1
  143. self.thread.save()
  144. # update forum
  145. if self.mode != EDIT:
  146. self.forum.set_last_thread(self.thread)
  147. self.forum.posts += 1
  148. self.forum.save()
  149. # update poster
  150. if self.mode == START:
  151. self.user.threads = F('threads') + 1
  152. if self.mode != EDIT:
  153. self.user.posts = F('posts') + 1
  154. self.user.save(update_fields=['threads', 'posts'])