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