PageRenderTime 26ms CodeModel.GetById 10ms RepoModel.GetById 0ms app.codeStats 0ms

/comment_utils/templatetags/moderated_comments.py

http://django-comment-utils.googlecode.com/
Python | 192 lines | 182 code | 5 blank | 5 comment | 5 complexity | 5324adb5bd0dceab201ed76ede442a8b MD5 | raw file
Possible License(s): BSD-3-Clause
  1. """
  2. Template tags designed to work with applications which use comment
  3. moderation.
  4. """
  5. from django import template
  6. from django.core.exceptions import ObjectDoesNotExist
  7. from django.db.models import get_model
  8. from django.contrib.comments.models import Comment, FreeComment
  9. from django.contrib.comments.templatetags import comments
  10. from django.contrib.contenttypes.models import ContentType
  11. from comment_utils.moderation import moderator
  12. class PublicCommentCountNode(comments.CommentCountNode):
  13. def render(self, context):
  14. from django.conf import settings
  15. manager = self.free and FreeComment.objects or Comment.objects
  16. if self.context_var_name is not None:
  17. object_id = self.context_var_name.resolve(context)
  18. comment_count = manager.filter(object_id__exact=object_id,
  19. content_type__app_label__exact=self.package,
  20. content_type__model__exact=self.module,
  21. site__id__exact=settings.SITE_ID,
  22. is_public__exact=True).count()
  23. context[self.var_name] = comment_count
  24. return ''
  25. class DoPublicCommentList(comments.DoGetCommentList):
  26. """
  27. Retrieves comments for a particular object and stores them in a
  28. context variable.
  29. The difference between this tag and Django's built-in comment list
  30. tags is that this tag will only return comments with
  31. ``is_public=True``. If your application uses any sort of comment
  32. moderation which sets ``is_public=False``, you'll probably want to
  33. use this tag, as it makes the template logic simpler by only
  34. returning approved comments.
  35. Syntax::
  36. {% get_public_comment_list for [app_name].[model_name] [object_id] as [varname] %}
  37. or::
  38. {% get_public_free_comment_list for [app_name].[model_name] [object_id] as [varname] %}
  39. When called as ``get_public_comment_list``, this tag retrieves
  40. instances of ``Comment`` (comments which require
  41. registration). When called as ``get_public_free_comment_list``,
  42. this tag retrieves instances of ``FreeComment`` (comments which do
  43. not require registration).
  44. To retrieve comments in reverse order (e.g., newest comments
  45. first), pass 'reversed' as an extra argument after ``varname``.
  46. So, for example, to retrieve registered comments for a flatpage
  47. with ``id`` 12, use like this::
  48. {% get_public_comment_list for flatpages.flatpage 12 as comment_list %}
  49. To retrieve unregistered comments for the same object::
  50. {% get_public_free_comment_list for flatpages.flatpage 12 as comment_list %}
  51. To retrieve in reverse order (newest comments first)::
  52. {% get_public_free_comment_list for flatpages.flatpage 12 as comment_list reversed %}
  53. """
  54. def __call__(self, parser, token):
  55. bits = token.contents.split()
  56. if len(bits) not in (6, 7):
  57. raise template.TemplateSyntaxError("'%s' tag takes 5 or 6 arguments" % bits[0])
  58. if bits[1] != 'for':
  59. raise template.TemplateSyntaxError("first argument to '%s' tag must be 'for'" % bits[0])
  60. try:
  61. app_name, model_name = bits[2].split('.')
  62. except ValueError:
  63. raise template.TemplateSyntaxError("second argument to '%s' tag must be in the form 'app_name.model_name'" % bits[0])
  64. model = get_model(app_name, model_name)
  65. if model is None:
  66. raise template.TemplateSyntaxError("'%s' tag got invalid model '%s.%s'" % (bits[0], app_name, model_name))
  67. content_type = ContentType.objects.get_for_model(model)
  68. var_name, object_id = None, None
  69. if bits[3].isdigit():
  70. object_id = bits[3]
  71. try:
  72. content_type.get_object_for_this_type(pk=object_id)
  73. except ObjectDoesNotExist:
  74. raise template.TemplateSyntaxError("'%s' tag got reference to %s object with id %s, which doesn't exist" % (bits[0], content_type.name, object_id))
  75. else:
  76. var_name = bits[3]
  77. if bits[4] != 'as':
  78. raise template.TemplateSyntaxError("fourth argument to '%s' tag must be 'as'" % bits[0])
  79. if len(bits) == 7:
  80. if bits[6] != 'reversed':
  81. raise template.TemplateSyntaxError("sixth argument to '%s' tag, if given, must be 'reversed'" % bits[0])
  82. ordering = '-'
  83. else:
  84. ordering = ''
  85. return comments.CommentListNode(app_name, model_name, var_name, object_id, bits[5], self.free, ordering, extra_kwargs={ 'is_public__exact': True })
  86. class DoPublicCommentCount(comments.DoCommentCount):
  87. """
  88. Retrieves the number of comments attached to a particular object
  89. and stores them in a context variable.
  90. The difference between this tag and Django's built-in comment
  91. count tags is that this tag will only count comments with
  92. ``is_public=True``. If your application uses any sort of comment
  93. moderation which sets ``is_public=False``, you'll probably want to
  94. use this tag, as it gives an accurate count of the comments which
  95. will be publicly displayed.
  96. Syntax::
  97. {% get_public_comment_count for [app_name].[model_name] [object_id] as [varname] %}
  98. or::
  99. {% get_public_free_comment_count for [app_name].[model_name] [object_id] as [varname] %}
  100. Example::
  101. {% get_public_comment_count for weblog.entry entry.id as comment_count %}
  102. When called as ``get_public_comment_list``, this tag counts
  103. instances of ``Comment`` (comments which require
  104. registration). When called as ``get_public_free_comment_count``,
  105. this tag counts instances of ``FreeComment`` (comments which do
  106. not require registration).
  107. """
  108. def __call__(self, parser, token):
  109. bits = token.contents.split()
  110. if len(bits) != 6:
  111. raise template.TemplateSyntaxError("'%s' tag takes five arguments" % bits[0])
  112. if bits[1] != 'for':
  113. raise template.TemplateSyntaxError("first argument to '%s' tag must be 'for'" % bits[0])
  114. try:
  115. app_name, model_name = bits[2].split('.')
  116. except ValueError:
  117. raise template.TemplateSyntaxError("second argument to '%s tag must be in the format app_name.model_name'" % bits[0])
  118. model = get_model(app_name, model_name)
  119. if model is None:
  120. raise template.TemplateSyntaxError("'%s' tag got invalid model '%s.%s'" % (bits[0], app_name, model_name))
  121. content_type = ContentType.objects.get_for_model(model)
  122. var_name, object_id = None, None
  123. if bits[3].isdigit():
  124. object_id = bits[3]
  125. try:
  126. content_type.get_object_for_this_type(pk=object_id)
  127. except ObjectDoesNotExist:
  128. raise template.TemplateSyntaxError("'%s' tag got reference to %s object with id %s, which doesn't exist" % (bits[0], content_type.name, object_id))
  129. else:
  130. var_name = bits[3]
  131. if bits[4] != 'as':
  132. raise template.TemplateSyntaxError("fourth argument to '%s' tag must be 'as'" % bits[0])
  133. return PublicCommentCountNode(app_name, model_name, var_name, object_id, bits[5], self.free)
  134. def comments_open(value):
  135. """
  136. Return ``True`` if new comments are allowed for an object,
  137. ``False`` otherwise.
  138. """
  139. return moderator.comments_open(value)
  140. def comments_moderated(value):
  141. """
  142. Return ``True`` if new comments for an object are being
  143. automatically sent into moderation, ``False`` otherwise.
  144. """
  145. return moderator.comments_moderated(value)
  146. register = template.Library()
  147. register.tag('get_public_comment_list', DoPublicCommentList(False))
  148. register.tag('get_public_free_comment_list', DoPublicCommentList(True))
  149. register.tag('get_public_comment_count', DoPublicCommentCount(False))
  150. register.tag('get_public_free_comment_count', DoPublicCommentCount(True))
  151. register.filter(comments_open)
  152. register.filter(comments_moderated)