def navitem(parser, token): """{% navitem <viewname> <title> [exact] %}""" tokens = token.split_contents() if len(tokens) < 3: raise TemplateSyntaxError("%s requires at least 3 tokens" % tokens[0]) return NavitemNode(*tokens[1:])
def _scan_placeholders(nodelist, current_block=None, ignore_blocks=None): from cms.templatetags.cms_tags import Placeholder placeholders = [] if ignore_blocks is None: # List of BlockNode instances to ignore. # This is important to avoid processing overriden block nodes. ignore_blocks = [] for node in nodelist: # check if this is a placeholder first if isinstance(node, Placeholder): placeholders.append(node.get_name()) elif isinstance(node, IncludeNode): # if there's an error in the to-be-included template, node.template becomes None if node.template: # This is required for Django 1.7 but works on older version too # Check if it quacks like a template object, if not # presume is a template path and get the object out of it if not callable(getattr(node.template, 'render', None)): template = get_template(node.template.var) else: template = node.template placeholders += _scan_placeholders(template.nodelist, current_block) # handle {% extends ... %} tags elif isinstance(node, ExtendsNode): placeholders += _extend_nodelist(node) # in block nodes we have to scan for super blocks elif isinstance(node, VariableNode) and current_block: if node.filter_expression.token == 'block.super': if not hasattr(current_block.super, 'nodelist'): raise TemplateSyntaxError( "Cannot render block.super for blocks without a parent." ) placeholders += _scan_placeholders( current_block.super.nodelist, current_block.super) # ignore nested blocks which are already handled elif isinstance(node, BlockNode) and node.name in ignore_blocks: continue # if the node has the newly introduced 'child_nodelists' attribute, scan # those attributes for nodelists and recurse them elif hasattr(node, 'child_nodelists'): for nodelist_name in node.child_nodelists: if hasattr(node, nodelist_name): subnodelist = getattr(node, nodelist_name) if isinstance(subnodelist, NodeList): if isinstance(node, BlockNode): current_block = node placeholders += _scan_placeholders( subnodelist, current_block, ignore_blocks) # else just scan the node for nodelist instance attributes else: for attr in dir(node): obj = getattr(node, attr) if isinstance(obj, NodeList): if isinstance(node, BlockNode): current_block = node placeholders += _scan_placeholders(obj, current_block, ignore_blocks) return placeholders
def reverse(parser, token): """ Returns an absolute URL matching given view with its parameters. This is a way to define links that aren't tied to a particular URL configuration:: {% reverse "path.to.some_view" "arg1","arg2" [as varname] %} or: {% reverse "path.to.some_view" name1="value1" [as varname] %} The first argument is a path to a view or a view name. It can be an absolute python path or just ``app_name.view_name`` without the project name if the view is located inside the project. Other arguments are comma-separated values that will be filled in place of positional and keyword arguments in the URL. All arguments for the URL must be present unless you use the ``partial`` form of ``reverse`` which is described below. If you'd like to store the resulting url in a ``context`` variable instead of directly displaying it you can use the optional ``as varname`` argument. For example if you have a view ``app_name.client`` taking client's id and the corresponding line in a URLconf looks like this:: ('^client/(\d+)/$', 'app_name.client') and this app's URLconf is included into the project's URLconf under some path:: ('^clients/', include('project_name.app_name.urls')) then in a template you can create a link for a certain client like this:: {% reverse "app_name.client" client.id %} The URL will look like ``/clients/client/123/``. Advanced usage ~~~~~~~~~~~~~~ The ``reverse`` tag also supports a more advanced mode of operation called "partial resolving". This allows you to reverse an URL in two or more stages. Each time only specifying some of required view arguments until the URL is resolved. Syntax: {% reverse partial "path.to.some_view" "arg1" key1="value1" as varname %} TODO: add more doc and usage examples Note: When using the partial keyword the ``as varname`` clause is required since a partially reversed URL can not be output directly but only be used as the ``view`` argument to another invocation of ``reverse``. Note: The "last" invocation MUST NOT specify ``partial`` """ bits = token.contents.split(' ') if len(bits) < 2: raise TemplateSyntaxError("'%s' takes at least one argument" " (path to a view)" % bits[0]) partial = False args = [] kwargs = {} asvar = None argstart = 2 if bits[1] == "partial": partial = True view = parser.compile_filter(bits[2]) argstart = 3 else: view = parser.compile_filter(bits[1]) if len(bits) > 2: bits = iter(bits[argstart:]) for bit in bits: if bit == 'as': asvar = bits.next() break else: for arg in bit.split(","): if '=' in arg: k, v = arg.split('=', 1) k = k.strip() kwargs[k] = parser.compile_filter(v) elif arg: args.append(parser.compile_filter(arg)) if partial and asvar is None: raise TemplateSyntaxError("When using 'partial' '%s' requires" " (as varname) argument" % bits[0]) if partial: return PartialReverseNode(view, args, kwargs, asvar) return ReverseNode(view, args, kwargs, asvar)
def get_imgix(image_url, alias=None, wh=None, **kwargs): try: domains = settings.IMGIX_DOMAINS except: raise ImproperlyConfigured( "IMGIX_DOMAINS not set in settings.py" ) ### Build arguments args = {} # Get arguments from settings shard_strategy, sign_key, use_https, aliases,\ format_detect, web_proxy = get_settings_variables() args['use_https'] = use_https if sign_key: args['sign_key'] = sign_key if shard_strategy: args['shard_strategy'] = shard_strategy # Imgix by default appends ?ixlib=python-<version_number> to the end # of the URL, but we don't want that. args['include_library_param'] = False # Get builder instance builder = imgix.UrlBuilder( domains, **args ) # Has the wh argument been passed? If yes, # set w and h arguments accordingly if wh: size = wh if isinstance(size, six.string_types): m = WH_PATTERN.match(size) if m: w = int(m.group(1)) h = int(m.group(2)) if w > 0: kwargs['w'] = int(m.group(1)) if h > 0: kwargs['h'] = int(m.group(2)) else: raise TemplateSyntaxError( "%r is not a valid size." % size ) # Is format detection on? If yes, use the appropriate image format. arguments = get_kwargs(alias, aliases, kwargs) if format_detect and 'fm' not in arguments: fm = get_fm(image_url) if fm: arguments['fm'] = fm # Take only the relative path of the URL if the source is not a Web Proxy Source if not web_proxy: image_url = urlparse(image_url).path # Build the Imgix URL url = builder.create_url(image_url, arguments) return mark_safe(url)
def parse(cls, parser, tokens): bits = tokens.split_contents() if len(bits) != 2: raise TemplateSyntaxError("{% widget %} takes one and only one argument") field = bits.pop(1) return cls(field)
def analytical_tag(parser, token): bits = token.split_contents() if len(bits) > 1: raise TemplateSyntaxError("'%s' tag takes no arguments" % bits[0]) return AnalyticalNode(location)
def do_t(parser, token): """ Parse a transifex translation tag. Inline syntax: {% t/ut <source>[|filter...] [key=param[|filter...]...] [as <var>] %} <source> can either be a literal string or a variable containing a string. In each case, the string will be considered an ICU template whose parameters will be rendered against the parameters of the tag and the context of the template. Block syntax: {% t/ut [|filter...] [key=param[|filter...]...] [as <var>] %} <source> {% endt/ut %} <source> can be anything. Django template tokens will not be parsed, but captured verbatim (which will most likely mess up with ICU formatting). Arguments: :param parser: A django Parser object. Has information about how the templating engine is setup, what filters and tags are available and the tokens that haven't yet been processed :param token: A django Token instance. Has information about the contents of the token we are currently processing """ # We will gradually "consume" bits left-to-right. At any given moment, the # leftmost bit is the one we need to be processing bits = list(token.split_contents()) # {% t ... %} # ^ tag_name = bits.pop(0) # not {% t %} has_args = bool(bits) # {% t |escapejs ... %} ... {% endt %} first_arg_is_filter = has_args and bits[0].startswith('|') # {% t "hello world" ... %} first_arg_is_string_literal = (has_args and bits[0][0] in ('"', "'") and bits[0][0] == bits[0][-1]) # {% t var=var ... %} first_arg_is_param = (has_args and not first_arg_is_string_literal and '=' in bits[0]) # {% t as text %} first_arg_is_as = has_args and bits[0] == "as" is_block = (not has_args or first_arg_is_filter or first_arg_is_param or first_arg_is_as) if not is_block: # Treat the source string as a full filter expression. Proper # exceptions will be raised if it is not formatted properly source_string = parser.compile_filter(bits.pop(0)) else: block = [] while True: try: # `next_token` removes the first token from the parser's list token = parser.next_token() except IndexError: # We ran out of tokens raise TemplateSyntaxError( "'{tag_name}' tag not closed with " "'end{tag_name}'".format(tag_name=tag_name)) if (token.token_type == TOKEN_BLOCK and token.contents == "end{}".format(tag_name)): break # Here we capture the contents of the block verbatim. # Unfortunately, there is some loss of information here: When # django captures a token, it saves the content as # `text[2:-2].strip()`, which means that the size of the # surrounding spaces is lost. This means that we end up capturing # `{% tag%}` as `{% tag %}` if token.token_type == TOKEN_VAR: block.append(''.join((VARIABLE_TAG_START, ' ', token.contents, ' ', VARIABLE_TAG_END))) elif token.token_type == TOKEN_BLOCK: block.append(''.join((BLOCK_TAG_START, ' ', token.contents, ' ', BLOCK_TAG_END))) elif token.token_type == TOKEN_COMMENT and token.contents: block.append(''.join((COMMENT_TAG_START, ' ', token.contents, ' ', COMMENT_TAG_END))) elif token.token_type == TOKEN_TEXT: block.append(token.contents) else: # pragma: no cover # Unreachable code raise TemplateSyntaxError("Could not parse body of '{}' tag " "block".format(tag_name)) block = ''.join(block) # Create a dummy filter expression with the provided filters and then # replace its 'var' attribute with the captured text. This effectively # makes # `{% t %}text{% endt %}` equivalent to `{% t "text" %}` and # `{% t |filter %}text{% endt %}` equivalent to `{% t "text"|filter %}` # while allowing the text to contain characters that would be invalid # with the inline syntax, like newlines and `"` if first_arg_is_filter: source_string = parser.compile_filter('""' + bits.pop(0)) else: source_string = parser.compile_filter('""') source_string.var = block # {% t "string" var=value var2=value2 ... %} # ^^^^^^^^^ params_list = [] while bits and '=' in bits[0]: params_list.append(bits.pop(0)) # Proper exceptions will be raised if the params are not formatted properly params = token_kwargs(params_list, parser, support_legacy=False) # {% t "string" as var %} # ^^^^^^ asvar = None if bits: if len(bits) != 2 or bits[0] != "as": raise TemplateSyntaxError("Unrecognized tail: {}".format( ' '.join(bits))) else: asvar = bits[1] del bits[:2] if bits: raise TemplateSyntaxError("Unrecognized tail: {}".format( ' '.join(bits))) return TNode(tag_name, source_string, params, asvar)
def render(self, context): cache_name = self.fragment_name.resolve(context) result = cache.get(cache_name) if not result: timeout = None if self.timeout_var: try: timeout = self.timeout_var.resolve(context) except VariableDoesNotExist: raise TemplateSyntaxError( '"cache" tag got an unknkown variable: {0}'.format( self.timeout_var.var)) try: timeout = int(timeout) except (ValueError, TypeError): raise TemplateSyntaxError( '"cache" tag got a non-integer timeout value: {0}'. fomat(timeout)) tags = [x.resolve(context) for x in self.vary_on] if 'tags' in self.kwargs: tags += self.kwargs['tags'].resolve(context) # We can also add a new tags during nodelist is rendering. # And prevent caching. if not 'cache_tagging_prevent' in context: context['cache_tagging_prevent'] = False sub_context = copy.copy(context) sub_context['cache_tagging'] = set(tags) # Allows nested caching sub_context['cache_tagging_prevent'] = False result = self.nodelist.render(sub_context) tags = sub_context['cache_tagging'] # Prevent caching of ancestor if sub_context['cache_tagging_prevent']: context['cache_tagging_prevent'] = True prevent = sub_context['cache_tagging_prevent'] if 'request' in context: request = context['request'] if not hasattr(request, 'cache_tagging'): request.cache_tagging = set() if isinstance(request.cache_tagging, set): request.cache_tagging.update(tags) if context['cache_tagging_prevent']: prevent_cache_page(request) if not prevent: cache.set(cache_name, result, tags, timeout) else: cache.abort(cache_name) if 'nocache' in self.kwargs and self.kwargs['nocache'].resolve( context): context_dict = {} for d in context.dicts: context_dict.update(d) class Filters(object): pass filters = Filters() for k, v in self.filters.items(): setattr(filters, k, v) filters.escape = filters.force_escape context_dict.update({ 'context': context, 'render_to_string': render_to_string, 'cache': cache, 'nocache': nocache_handler, 'filters': filters, 'reverse': urlresolvers.reverse, '_': ugettext_lazy, 'ugettext_lazy': ugettext_lazy, '_p': pgettext_lazy, 'pgettext_lazy': pgettext_lazy, }) result = nocache_handler.handle(result, **context_dict) if 'phased' in self.kwargs and self.kwargs['phased'].resolve( context) and phased_render: # support for django-phased https://github.com/codysoyland/django-phased result = phased_render(context['request'], result) return result
def minified_js(sourcefile): if sourcefile not in settings.JS_SPECS: raise TemplateSyntaxError( "Invalid argument: no JS file %s".format(sourcefile)) return MinifiedJSNode(sourcefile).render({})
def reply_list(context, entry, comment, context_type, context_id): """ Renders a list of comments of a specified type. This is a complex, confusing function accepts lots of inputs in order to display replies to a type of object. In each case, the replies will be rendered using the template :template:`reviews/review_reply.html`. If ``context_type`` is ``"diff_comments"``, ``"screenshot_comments"`` or ``"file_attachment_comments"``, the generated list of replies are to ``comment``. If ``context_type`` is ``"body_top"`` or ```"body_bottom"``, the generated list of replies are to ``review``. Depending on the ``context_type``, these will either be replies to the top of the review body or to the bottom. The ``context_id`` parameter has to do with the internal IDs used by the JavaScript code for storing and categorizing the comments. """ def generate_reply_html(reply, timestamp, text, rich_text, comment_id=None): new_context = context new_context.update({ 'context_id': context_id, 'id': reply.id, 'review': review, 'timestamp': timestamp, 'text': text, 'reply_user': reply.user, 'draft': not reply.public, 'comment_id': comment_id, 'rich_text': rich_text, }) return render_to_string('reviews/review_reply.html', new_context) def process_body_replies(queryset, attrname, user): if user.is_anonymous(): queryset = queryset.filter(public=True) else: queryset = queryset.filter(Q(public=True) | Q(user=user)) s = "" for reply_comment in queryset: s += generate_reply_html(reply, reply.timestamp, getattr(reply, attrname)) return s review = entry['review'] user = context.get('user', None) if user.is_anonymous(): user = None s = "" if context_type in ('diff_comments', 'screenshot_comments', 'file_attachment_comments'): for reply_comment in comment.public_replies(user): s += generate_reply_html(reply_comment.get_review(), reply_comment.timestamp, reply_comment.text, reply_comment.rich_text, reply_comment.pk) elif context_type == "body_top" or context_type == "body_bottom": replies = getattr(review, "public_%s_replies" % context_type)() for reply in replies: s += generate_reply_html(reply, reply.timestamp, getattr(reply, context_type), reply.rich_text) return s else: raise TemplateSyntaxError("Invalid context type passed") return s
def _validate_no_args(token): bits = token.split_contents() if len(bits) > 1: raise TemplateSyntaxError("'%s' takes no arguments" % bits[0])
def render_xtdcomment_tree(parser, token): """ Render the nested comment tree structure posted to the given object. By default uses the template ``django_comments_xtd/comments_tree.html``. Syntax:: {% render_xtdcomment_tree [for <object>] [with vname1=<obj1> vname2=<obj2>] [allow_feedback] [show_feedback] [allow_flagging] [using <template>] %} {% render_xtdcomment_tree with <varname>=<context-var> %} Example usage:: {% render_xtdcomment_tree for object allow_feedback %} {% render_xtdcomment_tree with comments=comment.children %} """ obj = None cvars = [] allow_feedback = False show_feedback = False allow_flagging = False template_path = None tokens = token.contents.split() tag = tokens.pop(0) # There must be at least a 'for <object>' or a 'with vname=obj' clause. if len(tokens) < 2 or tokens[0] not in ["for", "with"]: raise TemplateSyntaxError("2nd and 3rd argument in %r must be either " "a 'for <object>' or a 'with vname=<obj>' " "clause." % tag) while tokens: token = tokens.pop(0) if token == "for": if tokens[0] != "with": obj = tokens[0] else: raise TemplateSyntaxError("3rd argument after 'for' in %r " "can't be reserved word 'with'." % tag) if token == "with": tail_tokens = [ "allow_feedback", "show_feedback", "allow_flagging", "using" ] try: if tokens[0] not in tail_tokens: while len(tokens) and tokens[0] not in tail_tokens: pair = tokens.pop(0) if pair.find("=") == -1: raise Exception() cvars.append(pair) else: raise Exception() except Exception: raise TemplateSyntaxError("arguments after 'with' in %r " "must be pairs varname=obj." % tag) if token == "allow_feedback": allow_feedback = True if token == "show_feedback": show_feedback = True if token == "allow_flagging": allow_flagging = True if token == "using": try: template_path = tokens[0] except IndexError: raise TemplateSyntaxError("The relative path to the template " "is missing after 'using' in %r." % tag) return RenderXtdCommentTreeNode(obj, cvars, allow_feedback=allow_feedback, show_feedback=show_feedback, allow_flagging=allow_flagging, template_path=template_path)
def do_settings(parser, token): bits = token.split_contents() if not len(bits) > 1: raise TemplateSyntaxError('%r tag requires at least one argument' % bits[0]) return SettingsNode(bits[1:])
def get_copyright(parser, token): bits = token.split_contents() if len(bits) != 2: raise TemplateSyntaxError('Error token tag "get_copyright"') return GetCopyrightNode(bits[1])
def bootstrap_pager(parser, token): """ Renders a Page object as a Twitter Bootstrap styled pager bar. Compatible with Bootstrap 2.x only. Example:: {% bootstrap_pager page_obj %} Named Parameters:: previous_label - The label to show for the Previous link (defaults to "Previous Page") next_label - The label to show for the Next link (defualts to "Next Page") previous_title - The link title for the previous link (defaults to "Previous Page") next_title - The link title for the next link (defaults to "Next Page") url_name - The named URL to use. Defaults to None. If None, then the default template simply appends the url parameter as a relative URL link, eg: <a href="?page=1">1</a> url_param_name - The name of the parameter to use in the URL. If url_name is set to None, this string is used as the parameter name in the relative URL path. If a URL name is specified, this string is used as the parameter name passed into the reverse() method for the URL. url_extra_args - This is used only in conjunction with url_name. When referencing a URL, additional arguments may be passed in as a list. url_extra_kwargs - This is used only in conjunction with url_name. When referencing a URL, additional named arguments may be passed in as a dictionary. url_get_params - The other get parameters to pass, only the page number will be overwritten. Use this to preserve filters. """ bits = token.split_contents() if len(bits) < 2: raise TemplateSyntaxError("'%s' takes at least one argument" " (Page object reference)" % bits[0]) page = parser.compile_filter(bits[1]) kwargs = {} bits = bits[2:] kwarg_re = re.compile(r'(\w+)=(.+)') if len(bits): for bit in bits: match = kwarg_re.match(bit) if not match: raise TemplateSyntaxError( "Malformed arguments to bootstrap_pagination pager tag") name, value = match.groups() kwargs[name] = parser.compile_filter(value) return BootstrapPagerNode(page, kwargs)
def salva(request): azienda = get_object_or_404(Azienda, pk__exact=request.session.get( 'azienda', False)) domandePostate = 0 questionario = Questionario.objects.get( pk__exact=request.POST.get('questionario_obj_id', False)) tmp = Domanda.objects.filter(questionario=questionario).filter( tipo=0).filter(multiple=True) Risultati.objects.filter(questionario=questionario, azienda=azienda, domanda__in=tmp).delete() for (counter, item) in enumerate(request.POST): ids = item.split('#') if (len(ids) == 2): id_questionario = ids[0] id_domanda = ids[1] if (len(ids) == 3): id_questionario = ids[0] id_domanda = ids[1] id_risposta = ids[2] if (len(ids) >= 2): # if counter == 0: # # tmp=Domanda.objects.filter(questionario=questionario).filter(tipo=0).filter(multiple=True) # Risultati.objects.filter(questionario=questionario,azienda=azienda,domanda__in=tmp).delete() domanda = get_object_or_404(Domanda, pk__exact=id_domanda) if int(domanda.tipo) != 1: domandePostate = domandePostate + 1 ''' risposta chiusa ''' if int(domanda.tipo) == 0: #domanda chiusa if domanda.multiple: risposte = request.POST.getlist(item) for risposta in risposte: try: risposta_chiusa = Risposta_chiusa.objects.get( id__exact=risposta) except: assert False, risposta risultato, created = Risultati.objects.get_or_create( azienda=azienda, domanda=domanda, risposta_chiusa=risposta_chiusa, questionario=questionario) risultato.testo = str(risposta) risultato.save() else: risposta = request.POST.get(item, False) try: risposta_chiusa = Risposta_chiusa.objects.get( id__exact=risposta) except: #boolean try: risposta_splitted = risposta.split('#') risposta_chiusa = Risposta_chiusa.objects.get( id__exact=risposta_splitted[0]) risposta = risposta_splitted[1] except: raise TemplateSyntaxError( "Errore nel salvataggio risposta chiusa. Name: %s Value: %s " % (item, risposta)) risultato, created = Risultati.objects.get_or_create( azienda=azienda, domanda=domanda, risposta_chiusa=risposta_chiusa, questionario=questionario) risultato.testo = str(risposta) risultato.save() ''' risposta di tipo range nome del campo = questionario#domanda#risposta valore = valore nel range ''' if int(domanda.tipo) == 2: #range risposta = request.POST.get(item, False) try: risposta_chiusa = Risposta_chiusa.objects.get( id__exact=ids[2]) except: assert False, risposta risultato, created = Risultati.objects.get_or_create( azienda=azienda, domanda=domanda, risposta_chiusa=risposta_chiusa, questionario=questionario) risultato.testo = str(risposta) risultato.save() ''' risposta aperta ''' if int(domanda.tipo) == 1: risposta_aperta = get_object_or_404(Risposta_aperta, id__exact=int(id_risposta)) risultato, created = Risultati.objects.get_or_create( azienda=azienda, domanda=domanda, risposta_aperta=risposta_aperta, questionario=questionario) risultato.testo = str(request.POST.get(item, '')) if risultato.testo != '': domandePostate = domandePostate + 1 risultato.save() ''' risposta modulare ''' if int(domanda.tipo) == 3: checkedFirst = False risposta_aperta = get_object_or_404(Risposta_aperta, id__exact=int(id_risposta)) Risultati.objects.filter( questionario=questionario, azienda=azienda, domanda=domanda, risposta_aperta=risposta_aperta).delete() for clustered in request.POST.getlist(item): if str(clustered) != '': risultato = Risultati( azienda=azienda, domanda=domanda, risposta_aperta=risposta_aperta, questionario=questionario, risposta_aperta_cluster=risposta_aperta) risultato.testo = str(clustered) if not checkedFirst: domandePostate = domandePostate + 1 checkedFirst = True risultato.save() # check del totale dei risultati # totDomande=0; if questionario: totDomande = len(questionario.domanda_set.all()) obj, created = GestoreQuestionari.objects.get_or_create( azienda=azienda, questionario=questionario) if domandePostate == totDomande: #questionario completo obj.status = 2 else: #questionario parziale obj.status = 1 obj.save() #assert False, "%s su %s" % (domandePostate,totDomande) return HttpResponseRedirect(request.META['HTTP_REFERER'])
def error(): raise TemplateSyntaxError( "mkrange accepts the syntax: {%% mkrange [start,] stop[, step] as context_name %%}, where 'start', 'stop' and 'step' must all be integers." )
def do_tag_cloud_for_model(parser, token): """ Retrieves a list of ``Tag`` objects for a given model, with tag cloud attributes set, and stores them in a context variable. Usage:: {% tag_cloud_for_model [model] as [varname] %} The model is specified in ``[appname].[modelname]`` format. Extended usage:: {% tag_cloud_for_model [model] as [varname] with [options] %} Extra options can be provided after an optional ``with`` argument, with each option being specified in ``[name]=[value]`` format. Valid extra options are: ``steps`` Integer. Defines the range of font sizes. ``min_count`` Integer. Defines the minimum number of times a tag must have been used to appear in the cloud. ``distribution`` One of ``linear`` or ``log``. Defines the font-size distribution algorithm to use when generating the tag cloud. Examples:: {% tag_cloud_for_model products.Widget as widget_tags %} {% tag_cloud_for_model products.Widget as widget_tags with steps=9 min_count=3 distribution=log %} """ bits = token.contents.split() len_bits = len(bits) if len_bits != 4 and len_bits not in range(6, 9): raise TemplateSyntaxError( _('%s tag requires either three or between five and seven arguments' ) % bits[0]) if bits[2] != 'as': raise TemplateSyntaxError( _("second argument to %s tag must be 'as'") % bits[0]) kwargs = {} if len_bits > 5: if bits[4] != 'with': raise TemplateSyntaxError( _("if given, fourth argument to %s tag must be 'with'") % bits[0]) for i in range(5, len_bits): try: name, value = bits[i].split('=') if name == 'steps' or name == 'min_count': try: kwargs[str(name)] = int(value) except ValueError: raise TemplateSyntaxError( _("%(tag)s tag's '%(option)s' option was not a valid integer: '%(value)s'" ) % { 'tag': bits[0], 'option': name, 'value': value, }) elif name == 'distribution': if value in ['linear', 'log']: kwargs[str(name)] = { 'linear': LINEAR, 'log': LOGARITHMIC }[value] else: raise TemplateSyntaxError( _("%(tag)s tag's '%(option)s' option was not a valid choice: '%(value)s'" ) % { 'tag': bits[0], 'option': name, 'value': value, }) else: raise TemplateSyntaxError( _("%(tag)s tag was given an invalid option: '%(option)s'" ) % { 'tag': bits[0], 'option': name, }) except ValueError: raise TemplateSyntaxError( _("%(tag)s tag was given a badly formatted option: '%(option)s'" ) % { 'tag': bits[0], 'option': bits[i], }) return TagCloudForModelNode(bits[1], bits[3], **kwargs)
def parse_bits(parser, bits, params, varargs, varkw, defaults, takes_context, name): """ Parses bits for template tag helpers (simple_tag, include_tag and assignment_tag), in particular by detecting syntax errors and by extracting positional and keyword arguments. """ if takes_context: if params[0] == 'context': params = params[1:] else: raise TemplateSyntaxError( "'%s' is decorated with takes_context=True so it must " "have a first argument of 'context'" % name) args = [] kwargs = {} unhandled_params = list(params) for bit in bits: # First we try to extract a potential kwarg from the bit kwarg = token_kwargs([bit], parser) if kwarg: # The kwarg was successfully extracted param, value = list(kwarg.items())[0] if param not in params and varkw is None: # An unexpected keyword argument was supplied raise TemplateSyntaxError( "'%s' received unexpected keyword argument '%s'" % (name, param)) elif param in kwargs: # The keyword argument has already been supplied once raise TemplateSyntaxError( "'%s' received multiple values for keyword argument '%s'" % (name, param)) else: # All good, record the keyword argument kwargs[str(param)] = value if param in unhandled_params: # If using the keyword syntax for a positional arg, then # consume it. unhandled_params.remove(param) else: if kwargs: raise TemplateSyntaxError( "'%s' received some positional argument(s) after some " "keyword argument(s)" % name) else: # Record the positional argument args.append(parser.compile_filter(bit)) try: # Consume from the list of expected positional arguments unhandled_params.pop(0) except IndexError: if varargs is None: raise TemplateSyntaxError( "'%s' received too many positional arguments" % name) if defaults is not None: # Consider the last n params handled, where n is the # number of defaults. unhandled_params = unhandled_params[:-len(defaults)] if unhandled_params: # Some positional arguments were not supplied raise TemplateSyntaxError( "'%s' did not receive value(s) for the argument(s): %s" % (name, ", ".join(["'%s'" % p for p in unhandled_params]))) return args, kwargs
def from_string(self, template_code): try: return Template(template_code) except MakoException: message = text_error_template().render() raise TemplateSyntaxError(message) # lint-amnesty, pylint: disable=raise-missing-from
def page_menu(context, token): """ Return a list of child pages for the given parent, storing all pages in a dict in the context when first called using parents as keys for retrieval on subsequent recursive calls from the menu template. """ # First arg could be the menu template file name, or the parent page. # Also allow for both to be used. template_name = None parent_page = None parts = token.split_contents()[1:] for part in parts: part = Variable(part).resolve(context) if isinstance(part, str): template_name = part elif isinstance(part, Page): parent_page = part if template_name is None: try: template_name = context["menu_template_name"] except KeyError: error = "No template found for page_menu in: %s" % parts raise TemplateSyntaxError(error) context["menu_template_name"] = template_name if "menu_pages" not in context: try: user = context["request"].user slug = context["request"].path except KeyError: user = None slug = "" num_children = lambda id: lambda: len(context["menu_pages"][id]) has_children = lambda id: lambda: num_children(id)() > 0 rel = [ m.__name__.lower() for m in Page.get_content_models() if not m._meta.proxy ] published = Page.objects.published(for_user=user).select_related(*rel) # Store the current page being viewed in the context. Used # for comparisons in page.set_menu_helpers. if "page" not in context: try: context.dicts[0]["_current_page"] = published.exclude( content_model="link").get(slug=slug) except Page.DoesNotExist: context.dicts[0]["_current_page"] = None elif slug: context.dicts[0]["_current_page"] = context["page"] # Some homepage related context flags. on_home is just a helper # indicated we're on the homepage. has_home indicates an actual # page object exists for the homepage, which can be used to # determine whether or not to show a hard-coded homepage link # in the page menu. home = home_slug() context.dicts[0]["on_home"] = slug == home context.dicts[0]["has_home"] = False # Maintain a dict of page IDs -> parent IDs for fast # lookup in setting page.is_current_or_ascendant in # page.set_menu_helpers. context.dicts[0]["_parent_page_ids"] = {} pages = defaultdict(list) for page in published.order_by("_order"): page.set_helpers(context) context["_parent_page_ids"][page.id] = page.parent_id setattr(page, "num_children", num_children(page.id)) setattr(page, "has_children", has_children(page.id)) pages[page.parent_id].append(page) if page.slug == home: context.dicts[0]["has_home"] = True # Include menu_pages in all contexts, not only in the # block being rendered. context.dicts[0]["menu_pages"] = pages # ``branch_level`` must be stored against each page so that the # calculation of it is correctly applied. This looks weird but if we do # the ``branch_level`` as a separate arg to the template tag with the # addition performed on it, the addition occurs each time the template # tag is called rather than once per level. context["branch_level"] = 0 parent_page_id = None if parent_page is not None: context["branch_level"] = getattr(parent_page, "branch_level", 0) + 1 parent_page_id = parent_page.id # Build the ``page_branch`` template variable, which is the list of # pages for the current parent. Here we also assign the attributes # to the page object that determines whether it belongs in the # current menu template being rendered. context["page_branch"] = context["menu_pages"].get(parent_page_id, []) context["page_branch_in_menu"] = False for page in context["page_branch"]: page.in_menu = page.in_menu_template(template_name) page.num_children_in_menu = 0 if page.in_menu: context["page_branch_in_menu"] = True for child in context["menu_pages"].get(page.id, []): if child.in_menu_template(template_name): page.num_children_in_menu += 1 page.has_children_in_menu = page.num_children_in_menu > 0 page.branch_level = context["branch_level"] page.parent = parent_page context["parent_page"] = page.parent # Prior to pages having the ``in_menus`` field, pages had two # boolean fields ``in_navigation`` and ``in_footer`` for # controlling menu inclusion. Attributes and variables # simulating these are maintained here for backwards # compatibility in templates, but will be removed eventually. page.in_navigation = page.in_menu page.in_footer = not (not page.in_menu and "footer" in template_name) if page.in_navigation: context["page_branch_in_navigation"] = True if page.in_footer: context["page_branch_in_footer"] = True t = get_template(template_name) return t.render(context.flatten())
def query_string(parser, token): """ Template tag for creating and modifying query strings. Syntax: {% query_string [<base_querystring>] [modifier]* [as <var_name>] %} modifier is <name><op><value> where op in {=, +, -} Parameters: - base_querystring: literal query string, e.g. '?tag=python&tag=django&year=2011', or context variable bound to either - a literal query string, - a python dict with potentially lists as values, or - a django QueryDict object May be '' or None or missing altogether. - modifiers may be repeated and have the form <name><op><value>. They are processed in the order they appear. name is taken as is for a parameter name. op is one of {=, +, -}. = replace all existing values of name with value(s) + add value(s) to existing values for name - remove value(s) from existing values if present value is either a literal parameter value or a context variable. If it is a context variable it may also be bound to a list. - as <var name>: bind result to context variable instead of injecting in output (same as in url tag). Examples: 1. {% query_string '?tag=a&m=1&m=3&tag=b' tag+'c' m=2 tag-'b' as myqs %} Result: myqs == '?m=2&tag=a&tag=c' 2. context = {'qs': {'tag': ['a', 'b'], 'year': 2011, 'month': 2}, 'tags': ['c', 'd'], 'm': 4,} {% query_string qs tag+tags month=m %} Result: '?tag=a&tag=b&tag=c&tag=d&year=2011&month=4 """ # matches 'tagname1+val1' or 'tagname1=val1' but not 'anyoldvalue' mod_re = re.compile(r"^(\w+)(=|\+|-)(.*)$") bits = token.split_contents() qdict = None mods = [] asvar = None bits = bits[1:] if len(bits) >= 2 and bits[-2] == 'as': asvar = bits[-1] bits = bits[:-2] if len(bits) >= 1: first = bits[0] if not mod_re.match(first): qdict = parser.compile_filter(first) bits = bits[1:] for bit in bits: match = mod_re.match(bit) if not match: raise TemplateSyntaxError( "Malformed arguments to query_string tag") name, op, value = match.groups() mods.append((name, op, parser.compile_filter(value))) return QueryStringNode(qdict, mods, asvar)
def enforce_form_tag(self, context): if not context.get(self.IN_FORM_CONTEXT_VAR, False): raise TemplateSyntaxError('%s must be used inside a form tag.' % self.tagname)
def do_block_translate(parser, token): """ This will translate a block of text with parameters. Usage:: {% blocktrans with foo|filter as bar and baz|filter as boo %} This is {{ bar }} and {{ boo }}. {% endblocktrans %} Additionally, this supports pluralization:: {% blocktrans count var|length as count %} There is {{ count }} object. {% plural %} There are {{ count }} objects. {% endblocktrans %} This is much like ngettext, only in template syntax. """ class BlockTranslateParser(TokenParser): def top(self): countervar = None counter = None extra_context = {} while self.more(): tag = self.tag() if tag == 'with' or tag == 'and': value = self.value() if self.tag() != 'as': raise TemplateSyntaxError( "variable bindings in 'blocktrans' must be 'with value as variable'" ) extra_context[self.tag()] = VariableNode( parser.compile_filter(value)) elif tag == 'count': counter = parser.compile_filter(self.value()) if self.tag() != 'as': raise TemplateSyntaxError( "counter specification in 'blocktrans' must be 'count value as variable'" ) countervar = self.tag() else: raise TemplateSyntaxError( "unknown subtag %s for 'blocktrans' found" % tag) return (countervar, counter, extra_context) countervar, counter, extra_context = BlockTranslateParser( token.contents).top() singular = [] plural = [] while parser.tokens: token = parser.next_token() if token.token_type in (TOKEN_VAR, TOKEN_TEXT): singular.append(token) else: break if countervar and counter: if token.contents.strip() != 'plural': raise TemplateSyntaxError( "'blocktrans' doesn't allow other block tags inside it") while parser.tokens: token = parser.next_token() if token.token_type in (TOKEN_VAR, TOKEN_TEXT): plural.append(token) else: break if token.contents.strip() != 'endblocktrans': raise TemplateSyntaxError( "'blocktrans' doesn't allow other block tags (seen %r) inside it" % token.contents) return BlockTranslateNode(extra_context, singular, plural, countervar, counter)
def do_block_translate(parser, token): """ This will translate a block of text with parameters. Usage:: {% blocktrans with bar=foo|filter boo=baz|filter %} This is {{ bar }} and {{ boo }}. {% endblocktrans %} Additionally, this supports pluralization:: {% blocktrans count count=var|length %} There is {{ count }} object. {% plural %} There are {{ count }} objects. {% endblocktrans %} This is much like ngettext, only in template syntax. The "var as value" legacy format is still supported:: {% blocktrans with foo|filter as bar and baz|filter as boo %} {% blocktrans count var|length as count %} Contextual translations are supported:: {% blocktrans with bar=foo|filter context "greeting" %} This is {{ bar }}. {% endblocktrans %} This is equivalent to calling pgettext/npgettext instead of (u)gettext/(u)ngettext. """ bits = token.split_contents() options = {} remaining_bits = bits[1:] while remaining_bits: option = remaining_bits.pop(0) if option in options: raise TemplateSyntaxError('The %r option was specified more ' 'than once.' % option) if option == 'with': value = token_kwargs(remaining_bits, parser, support_legacy=True) if not value: raise TemplateSyntaxError('"with" in %r tag needs at least ' 'one keyword argument.' % bits[0]) elif option == 'count': value = token_kwargs(remaining_bits, parser, support_legacy=True) if len(value) != 1: raise TemplateSyntaxError('"count" in %r tag expected exactly ' 'one keyword argument.' % bits[0]) elif option == "context": try: value = remaining_bits.pop(0) value = parser.compile_filter(value) except Exception: raise TemplateSyntaxError('"context" in %r tag expected ' 'exactly one argument.' % bits[0]) else: raise TemplateSyntaxError('Unknown argument for %r tag: %r.' % (bits[0], option)) options[option] = value if 'count' in options: countervar, counter = options['count'].items()[0] else: countervar, counter = None, None if 'context' in options: message_context = options['context'] else: message_context = None extra_context = options.get('with', {}) singular = [] plural = [] while parser.tokens: token = parser.next_token() if token.token_type in (TOKEN_VAR, TOKEN_TEXT): singular.append(token) else: break if countervar and counter: if token.contents.strip() != 'plural': raise TemplateSyntaxError( "'blocktrans' doesn't allow other block tags inside it") while parser.tokens: token = parser.next_token() if token.token_type in (TOKEN_VAR, TOKEN_TEXT): plural.append(token) else: break if token.contents.strip() != 'endblocktrans': raise TemplateSyntaxError( "'blocktrans' doesn't allow other block tags (seen %r) inside it" % token.contents) return BlockTranslateNode(extra_context, singular, plural, countervar, counter, message_context)
def callback(func, variables, context, takes_context): """ resolve an iterable of Variable objects into a list of args and a dict of keyword arguments. support full python style keyword argument processing:: >>> def foo(a, b, c=1, d=2): ... pass >>> foo(1, 2) >>> foo(1, b=2) >>> foo(b=2, a=1, d=3) """ name = getattr(func, "_decorated_function", func).__name__ params, varargs, varkw, defaults = getargspec(func) if takes_context: if params[0] == 'context': params.pop(0) else: raise TemplateSyntaxError( "Any tag function decorated with takes_context=True " "must have a first argument of 'context'") num_defaults = len(defaults) num_params = len(params) num_req = num_params - num_defaults args = [] kwdargs = {} found_kwd = False for variable in variables: if not found_kwd: try: args.append(variable.resolve(context)) except VariableDoesNotExist: if variable.var.count(TAG_KEYWORD_ARGUMENT_SEPARATOR) != 1: raise found_kwd = True if found_kwd: try: var, path = variable.var.split(TAG_KEYWORD_ARGUMENT_SEPARATOR) except ValueError: raise TemplateSyntaxError( "Expected keyword assignemnt, found '%s' instead" % variable.var) if params and not varkw and name not in params: raise TemplateSyntaxError( "%s got an unexpected keyword argument '%s'" % (name, var)) if var in kwdargs: raise TemplateSyntaxError( "%s got multiple values for keyword argument '%s'" % (name, var)) kwdargs[smart_str(var)] = Variable(path).resolve(context) num_args = len(args) num_kwds = len(kwdargs) num_all = num_args + num_kwds if ((num_args > num_params and not varargs) or (num_all > num_params and not varkw)): raise TemplateSyntaxError("%s takes at most %s arguments. (%s given)" % (name, num_params, num_all)) if num_args != num_req: if num_args > num_req: # some args are kwd args (maybe multiple keyword error) if not varargs: allowed = set(params[num_args:]) not_allowed = set(kwdargs) - allowed if not_allowed: raise TemplateSyntaxError( "%s got multiple values for keyword arguments: %s" % (name, ", ".join(not_allowed))) elif not varkw: # not enough required parameters error required = set(params[num_args:-num_default]) missing = required - set(kwdargs) if missing: raise TemplateSyntaxError( "%s takes at least %s non-keyword arguments (%s given)" % (name, num_req, num_args)) if takes_context: args.insert(0, context) return func(*args, **kwdargs)
if not callback_js: callback_js = '(function(e) { window.location.href = document.location; })' module, dot, func = func.rpartition('.') try: module = import_module(module) except ImportError, ex: raise TemplateSyntaxError('Could not import module %s' % module, ex) try: func = getattr(module, func) except AttributeError, ex: raise TemplateSyntaxError( 'Could not load handler %s from module %s' % (func, module.__name__), ex ) if 'request' in context: request = context['request'] if request.method == 'POST' and '_bambu_fileupload_guid' in request.POST: guid = request.POST['_bambu_fileupload_guid'] else: guid = unicode(uuid4()) else: guid = None if not any(kwargs): kwargs = dict(guid = guid) if not style in ('drag', 'button'):
def bootstrap_paginate(parser, token): """ Renders a Page object as a Twitter Bootstrap styled pagination bar. Compatible with Bootstrap 3.x only. Example:: {% bootstrap_paginate page_obj range=10 %} Named Parameters:: range - The size of the pagination bar (ie, if set to 10 then, at most, 10 page numbers will display at any given time) Defaults to None, which shows all pages. size - Accepts "small", and "large". Defaults to None which is the standard size. show_prev_next - Accepts "true" or "false". Determines whether or not to show the previous and next page links. Defaults to "true" show_first_last - Accepts "true" or "false". Determines whether or not to show the first and last page links. Defaults to "false" previous_label - The text to display for the previous page link. Defaults to "←" next_label - The text to display for the next page link. Defaults to "→" first_label - The text to display for the first page link. Defaults to "«" last_label - The text to display for the last page link. Defaults to "»" url_name - The named URL to use. Defaults to None. If None, then the default template simply appends the url parameter as a relative URL link, eg: <a href="?page=1">1</a> url_param_name - The name of the parameter to use in the URL. If url_name is set to None, this string is used as the parameter name in the relative URL path. If a URL name is specified, this string is used as the parameter name passed into the reverse() method for the URL. url_extra_args - This is used only in conjunction with url_name. When referencing a URL, additional arguments may be passed in as a list. url_extra_kwargs - This is used only in conjunction with url_name. When referencing a URL, additional named arguments may be passed in as a dictionary. url_get_params - The other get parameters to pass, only the page number will be overwritten. Use this to preserve filters. """ bits = token.split_contents() if len(bits) < 2: raise TemplateSyntaxError("'%s' takes at least one argument" " (Page object reference)" % bits[0]) page = parser.compile_filter(bits[1]) kwargs = {} bits = bits[2:] kwarg_re = re.compile(r'(\w+)=(.+)') if len(bits): for bit in bits: match = kwarg_re.match(bit) if not match: raise TemplateSyntaxError( "Malformed arguments to bootstrap_pagination paginate tag") name, value = match.groups() kwargs[name] = parser.compile_filter(value) return BootstrapPaginationNode(page, kwargs)
def dummy_tag(parser, token): bits = token.split_contents() if len(bits) > 1: raise TemplateSyntaxError("'%s' tag takes no arguments" % bits[0]) return _location_nodes[location]
def drinker_name_tag(parser, token): """{% drinker_name <drink_or_user_obj> [nolink] %}""" tokens = token.contents.split() if len(tokens) < 2: raise TemplateSyntaxError("%s requires at least 2 tokens" % tokens[0]) return DrinkerNameNode(tokens[1], tokens[2:])