Ticket #20434: patch4.patch
File patch4.patch, 24.6 KB (added by , 11 years ago) |
---|
-
django/contrib/admin/templatetags/log.py
commit c96bf1a1ecf9427cdff8eab70bb9d973221f1881 Author: Jonathan Slenders <jonathan@slenders.be> Date: Thu Jun 6 00:28:36 2013 +0200 Refactoring of templatetags using the TemplateTag class in contrib. diff --git a/django/contrib/admin/templatetags/log.py b/django/contrib/admin/templatetags/log.py index 1b9e6aa..00a21f4 100644
a b from django.contrib.admin.models import LogEntry 3 3 4 4 register = template.Library() 5 5 6 class AdminLogNode(template.Node):7 def __init__(self, limit, varname, user):8 self.limit, self.varname, self.user = limit, varname, user9 10 def __repr__(self):11 return "<GetAdminLog Node>"12 13 def render(self, context):14 if self.user is None:15 context[self.varname] = LogEntry.objects.all().select_related('content_type', 'user')[:self.limit]16 else:17 user_id = self.user18 if not user_id.isdigit():19 user_id = context[self.user].pk20 context[self.varname] = LogEntry.objects.filter(user__pk__exact=user_id).select_related('content_type', 'user')[:int(self.limit)]21 return ''22 23 6 @register.tag 24 def get_admin_log(parser, token):7 class AdminLogNode(template.TemplateTag): 25 8 """ 26 9 Populates a template variable with the admin log for the given criteria. 27 10 … … def get_admin_log(parser, token): 39 22 (user ID) or the name of a template context variable containing the user 40 23 object whose ID you want. 41 24 """ 42 tokens = token.contents.split() 43 if len(tokens) < 4: 44 raise template.TemplateSyntaxError( 45 "'get_admin_log' statements require two arguments") 46 if not tokens[1].isdigit(): 47 raise template.TemplateSyntaxError( 48 "First argument to 'get_admin_log' must be an integer") 49 if tokens[2] != 'as': 50 raise template.TemplateSyntaxError( 51 "Second argument to 'get_admin_log' must be 'as'") 52 if len(tokens) > 4: 53 if tokens[4] != 'for_user': 25 grammar = template.Grammar('get_admin_log') 26 27 def __init__(self, parser, parse_result): 28 bits = parse_result.arguments 29 30 if len(bits) < 3: 54 31 raise template.TemplateSyntaxError( 55 "Fourth argument to 'get_admin_log' must be 'for_user'") 56 return AdminLogNode(limit=tokens[1], varname=tokens[3], user=(tokens[5] if len(tokens) > 5 else None)) 32 "'get_admin_log' statements require two arguments") 33 if not bits[0].isdigit(): 34 raise template.TemplateSyntaxError( 35 "First argument to 'get_admin_log' must be an integer") 36 if bits[1] != 'as': 37 raise template.TemplateSyntaxError( 38 "Second argument to 'get_admin_log' must be 'as'") 39 if len(bits) > 3: 40 if bits[3] != 'for_user': 41 raise template.TemplateSyntaxError( 42 "Fourth argument to 'get_admin_log' must be 'for_user'") 43 44 self.limit, self.varname, self.user = bits[0], bits[2], (bits[4] if len(bits) > 4 else None) 45 46 def __repr__(self): 47 return "<GetAdminLog Node>" 48 49 def render(self, context): 50 if self.user is None: 51 context[self.varname] = LogEntry.objects.all().select_related('content_type', 'user')[:self.limit] 52 else: 53 user_id = self.user 54 if not user_id.isdigit(): 55 user_id = context[self.user].pk 56 context[self.varname] = LogEntry.objects.filter(user__pk__exact=user_id).select_related('content_type', 'user')[:int(self.limit)] 57 return '' -
django/contrib/comments/templatetags/comments.py
diff --git a/django/contrib/comments/templatetags/comments.py b/django/contrib/comments/templatetags/comments.py index d8eed76..f98e72f 100644
a b class RenameBaseCommentNodeMethods(RenameMethodsBase): 16 16 ) 17 17 18 18 19 class BaseCommentNode(six.with_metaclass(RenameBaseCommentNodeMethods, template. Node)):19 class BaseCommentNode(six.with_metaclass(RenameBaseCommentNodeMethods, template.TemplateTag)): 20 20 """ 21 21 Base helper class (abstract) for handling the get_comment_* template tags. 22 22 Looks a bit strange, but the subclasses below should make this a bit more … … class BaseCommentNode(six.with_metaclass(RenameBaseCommentNodeMethods, template. 24 24 """ 25 25 26 26 @classmethod 27 def handle_ token(cls, parser, token):27 def handle_parse_result(cls, parser, parse_result): 28 28 """Class method to parse get_comment_list/count/form and return a Node.""" 29 tokens = token.split_contents() 30 if tokens[1] != 'for': 31 raise template.TemplateSyntaxError("Second argument in %r tag must be 'for'" % tokens[0]) 29 tokens = parse_result.arguments 30 tagname = parse_result.tagname 31 32 if tokens[0] != 'for': 33 raise template.TemplateSyntaxError("Second argument in %r tag must be 'for'" % tagname) 32 34 33 35 # {% get_whatever for obj as varname %} 34 if len(tokens) == 5:35 if tokens[ 3] != 'as':36 raise template.TemplateSyntaxError("Third argument in %r must be 'as'" % t okens[0])36 if len(tokens) == 4: 37 if tokens[2] != 'as': 38 raise template.TemplateSyntaxError("Third argument in %r must be 'as'" % tagname) 37 39 return cls( 38 object_expr = parser.compile_filter(tokens[ 2]),39 as_varname = tokens[ 4],40 object_expr = parser.compile_filter(tokens[1]), 41 as_varname = tokens[3], 40 42 ) 41 43 42 44 # {% get_whatever for app.model pk as varname %} 43 elif len(tokens) == 6:44 if tokens[ 4] != 'as':45 raise template.TemplateSyntaxError("Fourth argument in %r must be 'as'" % t okens[0])45 elif len(tokens) == 5: 46 if tokens[3] != 'as': 47 raise template.TemplateSyntaxError("Fourth argument in %r must be 'as'" % tagname) 46 48 return cls( 47 ctype = BaseCommentNode.lookup_content_type(tokens[ 2], tokens[0]),48 object_pk_expr = parser.compile_filter(tokens[ 3]),49 as_varname = tokens[ 5]49 ctype = BaseCommentNode.lookup_content_type(tokens[1], tagname), 50 object_pk_expr = parser.compile_filter(tokens[2]), 51 as_varname = tokens[4] 50 52 ) 51 53 52 54 else: 53 raise template.TemplateSyntaxError("%r tag requires 4 or 5 arguments" % t okens[0])55 raise template.TemplateSyntaxError("%r tag requires 4 or 5 arguments" % tagname) 54 56 55 57 @staticmethod 56 58 def lookup_content_type(token, tagname): … … class BaseCommentNode(six.with_metaclass(RenameBaseCommentNodeMethods, template. 114 116 """Subclasses should override this.""" 115 117 raise NotImplementedError 116 118 119 @register.tag 117 120 class CommentListNode(BaseCommentNode): 118 """Insert a list of comments into the context.""" 121 """ 122 Gets the list of comments for the given params and populates the template 123 context with a variable containing that value, whose name is defined by the 124 'as' clause. 125 126 Syntax:: 127 128 {% get_comment_list for [object] as [varname] %} 129 {% get_comment_list for [app].[model] [object_id] as [varname] %} 130 131 Example usage:: 132 133 {% get_comment_list for event as comment_list %} 134 {% for comment in comment_list %} 135 ... 136 {% endfor %} 137 138 """ 139 grammar = template.Grammar('get_comment_list') 140 119 141 def get_context_value_from_queryset(self, context, qs): 120 142 return list(qs) 121 143 144 @register.tag 122 145 class CommentCountNode(BaseCommentNode): 123 """Insert a count of comments into the context.""" 146 """ 147 Gets the comment count for the given params and populates the template 148 context with a variable containing that value, whose name is defined by the 149 'as' clause. 150 151 Syntax:: 152 153 {% get_comment_count for [object] as [varname] %} 154 {% get_comment_count for [app].[model] [object_id] as [varname] %} 155 156 Example usage:: 157 158 {% get_comment_count for event as comment_count %} 159 {% get_comment_count for calendar.event event.id as comment_count %} 160 {% get_comment_count for calendar.event 17 as comment_count %} 161 162 """ 163 grammar = template.Grammar('get_comment_count') 164 124 165 def get_context_value_from_queryset(self, context, qs): 125 166 return qs.count() 126 167 168 @register.tag 127 169 class CommentFormNode(BaseCommentNode): 128 """Insert a form for the comment model into the context.""" 170 """ 171 Get a (new) form object to post a new comment. 172 173 Syntax:: 174 175 {% get_comment_form for [object] as [varname] %} 176 {% get_comment_form for [app].[model] [object_id] as [varname] %} 177 """ 178 grammar = template.Grammar('get_comment_form') 129 179 130 180 def get_form(self, context): 131 181 obj = self.get_object(context) … … class CommentFormNode(BaseCommentNode): 149 199 context[self.as_varname] = self.get_form(context) 150 200 return '' 151 201 202 @register.tag 152 203 class RenderCommentFormNode(CommentFormNode): 153 """Render the comment form directly""" 204 """ 205 Render the comment form (as returned by ``{% render_comment_form %}``) through 206 the ``comments/form.html`` template. 207 208 Syntax:: 209 210 {% render_comment_form for [object] %} 211 {% render_comment_form for [app].[model] [object_id] %} 212 """ 213 grammar = template.Grammar('render_comment_form') 154 214 155 215 @classmethod 156 def handle_ token(cls, parser, token):216 def handle_parse_result(cls, parser, parse_result): 157 217 """Class method to parse render_comment_form and return a Node.""" 158 tokens = token.split_contents() 159 if tokens[1] != 'for': 160 raise template.TemplateSyntaxError("Second argument in %r tag must be 'for'" % tokens[0]) 218 tokens = parse_result.arguments 219 tagname = parse_result.tagname 220 221 if tokens[0] != 'for': 222 raise template.TemplateSyntaxError("Second argument in %r tag must be 'for'" % tagname) 161 223 162 224 # {% render_comment_form for obj %} 163 if len(tokens) == 3:164 return cls(object_expr=parser.compile_filter(tokens[ 2]))225 if len(tokens) == 2: 226 return cls(object_expr=parser.compile_filter(tokens[1])) 165 227 166 228 # {% render_comment_form for app.models pk %} 167 elif len(tokens) == 4:229 elif len(tokens) == 3: 168 230 return cls( 169 ctype = BaseCommentNode.lookup_content_type(tokens[ 2], tokens[0]),170 object_pk_expr = parser.compile_filter(tokens[ 3])231 ctype = BaseCommentNode.lookup_content_type(tokens[1], tagname), 232 object_pk_expr = parser.compile_filter(tokens[2]) 171 233 ) 172 234 173 235 def render(self, context): … … class RenderCommentFormNode(CommentFormNode): 185 247 else: 186 248 return '' 187 249 250 @register.tag 188 251 class RenderCommentListNode(CommentListNode): 189 """Render the comment list directly""" 252 """ 253 Render the comment list (as returned by ``{% get_comment_list %}``) 254 through the ``comments/list.html`` template 255 256 Syntax:: 257 258 {% render_comment_list for [object] %} 259 {% render_comment_list for [app].[model] [object_id] %} 260 261 Example usage:: 262 263 {% render_comment_list for event %} 264 265 """ 266 grammar = template.Grammar('render_comment_list') 190 267 191 268 @classmethod 192 def handle_ token(cls, parser, token):269 def handle_parse_result(cls, parser, parse_result): 193 270 """Class method to parse render_comment_list and return a Node.""" 194 tokens = token.split_contents() 195 if tokens[1] != 'for': 196 raise template.TemplateSyntaxError("Second argument in %r tag must be 'for'" % tokens[0]) 271 tokens = parse_result.arguments 272 tagname = parse_result.tagname 273 274 if tokens[0] != 'for': 275 raise template.TemplateSyntaxError("Second argument in %r tag must be 'for'" % tagname) 197 276 198 277 # {% render_comment_list for obj %} 199 if len(tokens) == 3:200 return cls(object_expr=parser.compile_filter(tokens[ 2]))278 if len(tokens) == 2: 279 return cls(object_expr=parser.compile_filter(tokens[1])) 201 280 202 281 # {% render_comment_list for app.models pk %} 203 elif len(tokens) == 4:282 elif len(tokens) == 3: 204 283 return cls( 205 ctype = BaseCommentNode.lookup_content_type(tokens[ 2], tokens[0]),206 object_pk_expr = parser.compile_filter(tokens[ 3])284 ctype = BaseCommentNode.lookup_content_type(tokens[1], tagname), 285 object_pk_expr = parser.compile_filter(tokens[2]) 207 286 ) 208 287 209 288 def render(self, context): … … class RenderCommentListNode(CommentListNode): 228 307 # the automagic docstrings-into-admin-docs tricks. So each node gets a cute 229 308 # wrapper function that just exists to hold the docstring. 230 309 231 @register.tag232 def get_comment_count(parser, token):233 """234 Gets the comment count for the given params and populates the template235 context with a variable containing that value, whose name is defined by the236 'as' clause.237 238 Syntax::239 240 {% get_comment_count for [object] as [varname] %}241 {% get_comment_count for [app].[model] [object_id] as [varname] %}242 243 Example usage::244 245 {% get_comment_count for event as comment_count %}246 {% get_comment_count for calendar.event event.id as comment_count %}247 {% get_comment_count for calendar.event 17 as comment_count %}248 249 """250 return CommentCountNode.handle_token(parser, token)251 252 @register.tag253 def get_comment_list(parser, token):254 """255 Gets the list of comments for the given params and populates the template256 context with a variable containing that value, whose name is defined by the257 'as' clause.258 259 Syntax::260 261 {% get_comment_list for [object] as [varname] %}262 {% get_comment_list for [app].[model] [object_id] as [varname] %}263 264 Example usage::265 266 {% get_comment_list for event as comment_list %}267 {% for comment in comment_list %}268 ...269 {% endfor %}270 271 """272 return CommentListNode.handle_token(parser, token)273 274 @register.tag275 def render_comment_list(parser, token):276 """277 Render the comment list (as returned by ``{% get_comment_list %}``)278 through the ``comments/list.html`` template279 280 Syntax::281 282 {% render_comment_list for [object] %}283 {% render_comment_list for [app].[model] [object_id] %}284 285 Example usage::286 287 {% render_comment_list for event %}288 289 """290 return RenderCommentListNode.handle_token(parser, token)291 292 @register.tag293 def get_comment_form(parser, token):294 """295 Get a (new) form object to post a new comment.296 297 Syntax::298 299 {% get_comment_form for [object] as [varname] %}300 {% get_comment_form for [app].[model] [object_id] as [varname] %}301 """302 return CommentFormNode.handle_token(parser, token)303 304 @register.tag305 def render_comment_form(parser, token):306 """307 Render the comment form (as returned by ``{% render_comment_form %}``) through308 the ``comments/form.html`` template.309 310 Syntax::311 312 {% render_comment_form for [object] %}313 {% render_comment_form for [app].[model] [object_id] %}314 """315 return RenderCommentFormNode.handle_token(parser, token)316 310 317 311 @register.simple_tag 318 312 def comment_form_target(): -
django/contrib/flatpages/templatetags/flatpages.py
diff --git a/django/contrib/flatpages/templatetags/flatpages.py b/django/contrib/flatpages/templatetags/flatpages.py index a32ac7f..aad0fc0 100644
a b from django import template 2 2 from django.conf import settings 3 3 from django.contrib.flatpages.models import FlatPage 4 4 from django.contrib.sites.models import get_current_site 5 from django.template.generic import TemplateTag, Grammar 5 6 6 7 7 8 register = template.Library() 8 9 9 10 class FlatpageNode(template.Node):11 def __init__(self, context_name, starts_with=None, user=None):12 self.context_name = context_name13 if starts_with:14 self.starts_with = template.Variable(starts_with)15 else:16 self.starts_with = None17 if user:18 self.user = template.Variable(user)19 else:20 self.user = None21 22 def render(self, context):23 if 'request' in context:24 site_pk = get_current_site(context['request']).pk25 else:26 site_pk = settings.SITE_ID27 flatpages = FlatPage.objects.filter(sites__id=site_pk)28 # If a prefix was specified, add a filter29 if self.starts_with:30 flatpages = flatpages.filter(31 url__startswith=self.starts_with.resolve(context))32 33 # If the provided user is not authenticated, or no user34 # was provided, filter the list to only public flatpages.35 if self.user:36 user = self.user.resolve(context)37 if not user.is_authenticated():38 flatpages = flatpages.filter(registration_required=False)39 else:40 flatpages = flatpages.filter(registration_required=False)41 42 context[self.context_name] = flatpages43 return ''44 45 46 10 @register.tag 47 def get_flatpages(parser, token):11 class FlatpageNode(TemplateTag): 48 12 """ 49 13 Retrieves all flatpage objects available for the current site and 50 14 visible to the specific user (or visible to all users if no user is … … def get_flatpages(parser, token): 71 35 {% get_flatpages prefix as about_pages %} 72 36 {% get_flatpages '/about/' for someuser as about_pages %} 73 37 """ 74 bits = token.split_contents() 75 syntax_message = ("%(tag_name)s expects a syntax of %(tag_name)s " 76 "['url_starts_with'] [for user] as context_name" % 77 dict(tag_name=bits[0])) 78 # Must have at 3-6 bits in the tag 79 if len(bits) >= 3 and len(bits) <= 6: 38 grammar = Grammar('get_flatpages') 39 40 def __init__(self, parser, parse_result): 41 bits = parse_result.arguments 42 tagname = parse_result.tagname 43 syntax_message = ("%(tag_name)s expects a syntax of %(tag_name)s " 44 "['url_starts_with'] [for user] as context_name" % 45 dict(tag_name=tagname)) 46 # Must have at 2-5 bits in the tag 47 if not (len(bits) >= 2 and len(bits) <= 5): 48 raise template.TemplateSyntaxError(syntax_message) 80 49 81 50 # If there's an even number of bits, there's no prefix 82 51 if len(bits) % 2 == 0: 83 prefix = bits[1]84 else:85 52 prefix = None 53 else: 54 prefix = bits[0] 86 55 87 56 # The very last bit must be the context name 88 57 if bits[-2] != 'as': 89 58 raise template.TemplateSyntaxError(syntax_message) 90 context_name = bits[-1]59 self.context_name = bits[-1] 91 60 92 # If there are 5 or 6bits, there is a user defined93 if len(bits) >= 5:61 # If there are 4 or 5 bits, there is a user defined 62 if len(bits) >= 4: 94 63 if bits[-4] != 'for': 95 64 raise template.TemplateSyntaxError(syntax_message) 96 65 user = bits[-3] 97 66 else: 98 67 user = None 99 68 100 return FlatpageNode(context_name, starts_with=prefix, user=user) 101 else: 102 raise template.TemplateSyntaxError(syntax_message) 69 self.starts_with = template.Variable(prefix) if prefix else None 70 self.user = template.Variable(user) if user else None 71 72 def render(self, context): 73 if 'request' in context: 74 site_pk = get_current_site(context['request']).pk 75 else: 76 site_pk = settings.SITE_ID 77 flatpages = FlatPage.objects.filter(sites__id=site_pk) 78 # If a prefix was specified, add a filter 79 if self.starts_with: 80 flatpages = flatpages.filter( 81 url__startswith=self.starts_with.resolve(context)) 82 83 # If the provided user is not authenticated, or no user 84 # was provided, filter the list to only public flatpages. 85 if self.user: 86 user = self.user.resolve(context) 87 if not user.is_authenticated(): 88 flatpages = flatpages.filter(registration_required=False) 89 else: 90 flatpages = flatpages.filter(registration_required=False) 91 92 context[self.context_name] = flatpages 93 return '' 94 95 -
django/contrib/staticfiles/templatetags/staticfiles.py
diff --git a/django/contrib/staticfiles/templatetags/staticfiles.py b/django/contrib/staticfiles/templatetags/staticfiles.py index ab92275..a9a66d8 100644
a b from django.contrib.staticfiles.storage import staticfiles_storage 5 5 register = template.Library() 6 6 7 7 8 @register.tag 8 9 class StaticFilesNode(StaticNode): 9 10 def url(self, context):11 path = self.path.resolve(context)12 return staticfiles_storage.url(path)13 14 15 @register.tag('static')16 def do_static(parser, token):17 10 """ 18 11 A template tag that returns the URL to a file 19 12 using staticfiles' storage backend … … def do_static(parser, token): 30 23 {% static variable_with_path as varname %} 31 24 32 25 """ 33 return StaticFilesNode.handle_token(parser, token) 26 grammar = template.Grammar('static') 27 28 def url(self, context): 29 path = self.path.resolve(context) 30 return staticfiles_storage.url(path) 34 31 35 32 36 33 def static(path): -
django/contrib/webdesign/templatetags/webdesign.py
diff --git a/django/contrib/webdesign/templatetags/webdesign.py b/django/contrib/webdesign/templatetags/webdesign.py index b870299..1a1a68d 100644
a b from __future__ import unicode_literals 2 2 3 3 from django.contrib.webdesign.lorem_ipsum import words, paragraphs 4 4 from django import template 5 from django.template.generic import TemplateTag, Grammar 5 6 6 7 register = template.Library() 7 8 8 class LoremNode(template.Node):9 def __init__(self, count, method, common):10 self.count, self.method, self.common = count, method, common11 12 def render(self, context):13 try:14 count = int(self.count.resolve(context))15 except (ValueError, TypeError):16 count = 117 if self.method == 'w':18 return words(count, common=self.common)19 else:20 paras = paragraphs(count, common=self.common)21 if self.method == 'p':22 paras = ['<p>%s</p>' % p for p in paras]23 return '\n\n'.join(paras)24 25 9 @register.tag 26 def lorem(parser, token):10 class LoremNode(TemplateTag): 27 11 """ 28 12 Creates random Latin text useful for providing test data in templates. 29 13 … … def lorem(parser, token): 46 30 and two random paragraphs each wrapped in HTML ``<p>`` tags 47 31 * ``{% lorem 2 w random %}`` will output two random latin words 48 32 """ 49 bits = list(token.split_contents()) 50 tagname = bits[0] 51 # Random bit 52 common = bits[-1] != 'random' 53 if not common: 54 bits.pop() 55 # Method bit 56 if bits[-1] in ('w', 'p', 'b'): 57 method = bits.pop() 58 else: 59 method = 'b' 60 # Count bit 61 if len(bits) > 1: 62 count = bits.pop() 63 else: 64 count = '1' 65 count = parser.compile_filter(count) 66 if len(bits) != 1: 67 raise template.TemplateSyntaxError("Incorrect format for %r tag" % tagname) 68 return LoremNode(count, method, common) 33 grammar = Grammar('lorem') 34 35 def __init__(self, parser, parse_result): 36 bits = parse_result.arguments[:] 37 tagname = parse_result.tagname 38 39 # Random bit 40 common = bits[-1] != 'random' 41 if not common: 42 bits.pop() 43 # Method bit 44 if bits[-1] in ('w', 'p', 'b'): 45 method = bits.pop() 46 else: 47 method = 'b' 48 # Count bit 49 if len(bits) > 0: 50 count = bits.pop() 51 else: 52 count = '1' 53 count = parser.compile_filter(count) 54 if len(bits) != 0: 55 raise template.TemplateSyntaxError("Incorrect format for %r tag" % tagname) 56 57 self.common = common 58 self.method = method 59 self.count = count 60 61 def render(self, context): 62 try: 63 count = int(self.count.resolve(context)) 64 except (ValueError, TypeError): 65 count = 1 66 if self.method == 'w': 67 return words(count, common=self.common) 68 else: 69 paras = paragraphs(count, common=self.common) 70 if self.method == 'p': 71 paras = ['<p>%s</p>' % p for p in paras] 72 return '\n\n'.join(paras)