Exemplo n.º 1
0
	def __init__(self, object_expr=None, name=None):
		if object_expr is None and name is None:
			raise template.TemplateSyntaxError("Like nodes must be given either a literal object.")

		self.object_expr = object_expr
		self.name = template.Variable(name)
Exemplo n.º 2
0
def _strip_quotes(arg):
    if not (arg[0] == arg[-1] and arg[0] in ('"', "'")):
        raise template.TemplateSyntaxError("Argument %s should be in quotes" %
                                           arg)
    return arg[1:-1]
Exemplo n.º 3
0
def get_pages(parser, token):
    """Add to context the list of page links.

    Usage:

    .. code-block:: html+django

        {% get_pages %}

    This is mostly used for Digg-style pagination.
    This call inserts in the template context a *pages* variable, as a sequence
    of page links. You can use *pages* in different ways:

    - just print *pages.get_rendered* and you will get Digg-style pagination displayed:

    .. code-block:: html+django

        {{ pages.get_rendered }}

    - display pages count:

    .. code-block:: html+django

        {{ pages|length }}

    - check if the page list contains more than one page:

    .. code-block:: html+django

        {{ pages.paginated }}
        {# the following is equivalent #}
        {{ pages|length > 1 }}

    - get a specific page:

    .. code-block:: html+django

        {# the current selected page #}
        {{ pages.current }}

        {# the first page #}
        {{ pages.first }}

        {# the last page #}
        {{ pages.last }}

        {# the previous page (or nothing if you are on first page) #}
        {{ pages.previous }}

        {# the next page (or nothing if you are in last page) #}
        {{ pages.next }}

        {# the third page #}
        {{ pages.3 }}
        {# this means page.1 is the same as page.first #}

        {# the 1-based index of the first item on the current page #}
        {{ pages.current_start_index }}

        {# the 1-based index of the last item on the current page #}
        {{ pages.current_end_index }}

        {# the total number of objects, across all pages #}
        {{ pages.total_count }}

        {# the first page represented as an arrow #}
        {{ pages.first_as_arrow }}

        {# the last page represented as an arrow #}
        {{ pages.last_as_arrow }}

    - iterate over *pages* to get all pages:

    .. code-block:: html+django

        {% for page in pages %}
            {# display page link #}
            {{ page.render_link}}

            {# the page url (beginning with "?") #}
            {{ page.url }}

            {# the page path #}
            {{ page.path }}

            {# the page number #}
            {{ page.number }}

            {# a string representing the page (commonly the page number) #}
            {{ page.label }}

            {# check if the page is the current one #}
            {{ page.is_current }}

            {# check if the page is the first one #}
            {{ page.is_first }}

            {# check if the page is the last one #}
            {{ page.is_last }}
        {% endfor %}

    You can change the variable name, e.g.:

    .. code-block:: html+django

        {% get_pages as page_links %}

    Must be called after ``{% paginate objects %}``.
    """
    # Validate args.
    try:
        tag_name, args = token.contents.split(None, 1)
    except ValueError:
        var_name = 'pages'
    else:
        args = args.split()
        if len(args) == 2 and args[0] == 'as':
            var_name = args[1]
        else:
            msg = 'Invalid arguments for %r tag' % tag_name
            raise template.TemplateSyntaxError(msg)
    # Call the node.
    return GetPagesNode(var_name)
Exemplo n.º 4
0
def auto_display(parser, token):
    """
    This tag returns an HTML element.

    Arguments::

      relation -- One object from the 'relations' template context object.
      prefix   -- A keyword argument who's value is used as a prefix to the
                  element id and name attributes.
      option   -- A keyword argument who's value is in the 'dynamicColumns'
                  context. The entire 'dynamicColumns' context can be supplied
                  or just the object for this relation.
      display  -- A keyword argument. If 'True' use <span> for all tags else
                  'False' use the default tag types.

    Assume data structures below for examples::

      {'dynamicColumns': {
        'book': [
          [0, 'Choose a value'],
          [2, 'HTML5 Pocket Reference'],
          [1, 'SQL Pocket Guide'],
          [3, 'Raspberry Pi Hacks']
          ]
        }
      }

      {'relations': {
        '1': {
          'name': 'Project ID',
          'required': false,
          'relation': null,
          'location': 'top-container',
          'value_type': 0,
          'order': 3,
          'value': '12345'
        },
      }

    Usage Examples::

      {% auto_display relation %}

      {% auto_display relation prefix=test- %}

      {% auto_display relation options=books %}

      {% auto_display relation options=books display=True %}

      {% auto_display relation prefix=test- options=dynamicColumns %}
    """
    tokens = token.split_contents()
    size = len(tokens)
    kwargs = {'prefix': '', 'options': None, 'display': 'False'}
    keywords = list(six.viewkeys(kwargs))
    keywords.sort()

    if size == 2:
        tag_name, relation = tokens
        kwargs = {}
    elif size == 3:
        tag_name, relation, value1 = tokens
        kwargs.update(
            {k: v
             for k, d, v in [v.partition('=') for v in (value1, )]})
    elif size == 4:
        tag_name, relation, value1, value2 = tokens
        kwargs.update(
            {k: v
             for k, d, v in [v.partition('=') for v in (value1, value2)]})
    elif size == 5:
        tag_name, relation, value1, value2, value3 = tokens
        kwargs.update({
            k: v
            for k, d, v in
            [v.partition('=') for v in (value1, value2, value3)]
        })
    else:
        msg = ("Invalid number of arguments should be 1 - 4, "
               "found: {}").format(size - 1)
        raise template.TemplateSyntaxError(msg)

    if size > 2 and not all([key in keywords for key in kwargs]):
        msg = "Invalid keyword name, should be one of {}".format(keywords)
        raise template.TemplateSyntaxError(msg)

    return AutoDisplayNode(tag_name, relation, **kwargs)
Exemplo n.º 5
0
        contents = token.contents.split()
        token_name, token_args = contents[0], contents[1:]
        
        if token_name == 'case':
            tests = map(parser.compile_filter, token_args)
            case = (tests, nodelist)
            got_case = True
        else:
            # The {% else %} tag
            case = (None, nodelist)
            got_else = True
        cases.append(case)
        token = parser.next_token()

    if not got_case:
        raise template.TemplateSyntaxError("'%s' must have at least one 'case'." % tag_name)

    return SwitchNode(variable, cases)

class SwitchNode(Node):
    def __init__(self, variable, cases):
        self.variable = variable
        self.cases = cases

    def __repr__(self):
        return "<Switch node>"

    def __iter__(self):
        for tests, nodelist in self.cases:
            for node in nodelist:
                yield node
Exemplo n.º 6
0
 def assign_vars(p_name, p_var):
     try:
         var[p_name] = p_var
     except KeyError:
         raise template.TemplateSyntaxError(error_msg)
Exemplo n.º 7
0
 def __init__(self, varname=None, path=None):
     if path is None:
         raise template.TemplateSyntaxError(
             "Static template nodes must be given a path to return.")
     self.path = path
     self.varname = varname
Exemplo n.º 8
0
def do_permission(parser, token):
    """
    permission tags for templates. At first, you must load custome tags from
    templatetags by {% load permission %}, and then use like following examples.

    A single block tags for check permission and display the context between
    them.

    ::

    {% permission 'right name' %}
        something want to be hidden if user does not have right
    {% endpermission %}


    A block tags with 'otherwise' that just like 'if-else' to choose which
    context to be displayed

    ::

    {% permission variable_from_request_context %}
        something want to be hidden if user does not have right
    {% otherwise %}
        show some warning tips or just leave it empty.
    {% endpermission %}


    """
    context = token.split_contents()
    if len(context) < 2:
        raise template.TemplateSyntaxError(
            "%r tag requires one right name at least" %
            token.contents.split()[0])

    rights = context[1:]
    nodelist = [parser.parse(('otherwise', 'endpermission'))]
    token = parser.next_token()

    # {% otherwise %}
    if token.contents == 'otherwise':
        nodelist.append(parser.parse(('endpermission', )))
        token = parser.next_token()

    # {% endpermission %}
    assert token.contents == 'endpermission'

    opt = 'and'
    if len(rights) == 1:
        filter_rights = rights
    else:
        l = len(rights)
        i = 0
        filter_rights = list()
        while i < l:
            token = rights[i]
            if token in ('or', 'and'):
                opt = token
            else:
                filter_rights.append(token)
            i += 1

    return PermissionNode(filter_rights, nodelist, opt)
Exemplo n.º 9
0
    def render(self, context):
        explanation = _resolve_variable(self.explanation, context)
        label, identifier = self.resolve_label_and_identifier(context)
        user = _resolve_variable(self.user, context)
        instance = _resolve_variable(self.instance, context)
        field_template = get_template(_resolve_variable(
                                      self.field_template, context)).template

        if not isinstance(identifier, basestring)\
           or not _identifier_regex.match(identifier):
            raise template.TemplateSyntaxError(
                'expected a string with the format "object_name.property" '
                'to follow "from" %s' % identifier)

        model_name_or_object_name, field_name = dotted_split(identifier, 2,
                                                             maxsplit=1)
        model = self.get_model(context, model_name_or_object_name, instance)

        object_name = to_object_name(model_name_or_object_name)

        identifier = "%s.%s" % (object_name, field_name)

        def _field_value(model, field_name, data_type):
            udf_field_name = field_name.replace('udf:', '')
            val = None
            if field_name in [f.name for f in model._meta.get_fields()]:
                try:
                    val = getattr(model, field_name)
                except (ObjectDoesNotExist, AttributeError):
                    pass
            elif _is_udf(model, udf_field_name):
                if udf_field_name in model.udfs:
                    val = model.udfs[udf_field_name]
                    # multichoices place a json serialized data-value
                    # on the dom element and client-side javascript
                    # processes it into a view table and edit widget
                    if data_type == 'multichoice':
                        val = json.dumps(val)
                elif data_type == 'multichoice':
                    val = '[]'
            else:
                raise ValueError('Could not find field: %s' % field_name)

            return val

        if is_json_field_reference(field_name):
            field_value = get_attr_from_json_field(model, field_name)
            choices = None
            is_visible = is_editable = True
            data_type = "string"
        else:
            add_blank = (ADD_BLANK_ALWAYS if self.treat_multichoice_as_choice
                         else ADD_BLANK_IF_CHOICE_FIELD)
            data_type, label, explanation, choices = field_type_label_choices(
                model, field_name, label, explanation=explanation,
                add_blank=add_blank)
            field_value = _field_value(model, field_name, data_type)

            if user is not None and hasattr(model, 'field_is_visible'):
                is_visible = model.field_is_visible(user, field_name)
                is_editable = model.field_is_editable(user, field_name)
            else:
                # This tag can be used without specifying a user. In that case
                # we assume that the content is visible and upstream code is
                # responsible for only showing the content to the appropriate
                # user
                is_visible = True
                is_editable = True

        digits = units = ''

        if hasattr(model, 'instance'):
            digits = get_digits_if_formattable(
                model.instance, object_name, field_name)

            units = get_units_if_convertible(
                model.instance, object_name, field_name)
            if units != '':
                units = get_unit_abbreviation(units)

        if data_type == 'foreign_key':
            # rendered clientside
            display_val = ''
        elif field_value is None:
            display_val = None
        elif data_type in ['date', 'datetime']:
            fmt = (model.instance.short_date_format if model.instance
                   else settings.SHORT_DATE_FORMAT)
            display_val = dateformat.format(field_value, fmt)
        elif is_convertible_or_formattable(object_name, field_name):
            display_val = format_value(
                model.instance, object_name, field_name, field_value)
            if units != '':
                display_val += (' %s' % units)
        elif data_type == 'bool':
            display_val = _('Yes') if field_value else _('No')
        elif data_type == 'multichoice':
            # this is rendered clientside from data attributes so
            # there's no meaningful intermediate value to send
            # without rendering the same markup server-side.
            display_val = None
        elif choices:
            display_vals = [choice['display_value'] for choice in choices
                            if choice['value'] == field_value]
            display_val = display_vals[0] if display_vals else field_value
        else:
            display_val = unicode(field_value)

        context['field'] = {
            'label': label,
            'explanation': explanation,
            'identifier': identifier,
            'value': field_value,
            'display_value': display_val,
            'units': units,
            'digits': digits,
            'data_type': data_type,
            'is_visible': is_visible,
            'is_editable': is_editable,
            'choices': choices,
        }
        self.get_additional_context(
            context['field'], model, field_name, context.get('q', ''))

        return field_template.render(context)
Exemplo n.º 10
0
def do_get_articles_most_commented(parser, token):
    bits = token.split_contents()
    if len(bits) != 3:
        raise template.TemplateSyntaxError(
            "'get_articles_most_commented' tag takes exactly 3 arguments")
    return MostCommentedNode(bits[2])
Exemplo n.º 11
0
def do_filter_url(parser, token):
    """
    Outputs a URL based on the filter chain, with optional
    additions/removals of filters.  The first argument is required
    and can be either an existing FilterChain or a Schema.

    {% filter_url filter_chain %}
    {% filter_url schema %}

    To remove a NewsitemFilter from the url, specify the key with a leading "-".

    {% filter_url filter_chain -key_to_remove %}
    {% filter_url filter_chain -"key_to_remove" %}
    {% filter_url filter_chain -key1 -key2 ... %}

    To add NewsitemFilters to the url, specify the key with a leading "+",
    followed by args to use for constructing a NewsitemFilter.

    {% filter_url filter_chain +"key" value %}
    {% filter_url filter_chain +key value1 value 2 ... %}
    {% filter_url filter_chain +key1 "arg1a" "arg1b" +key2 "arg2a" ... %}

    You can even mix and match additions and removals:

    {% filter_url filter_chain -key1 +key2 arg2 -key3 +key4 arg4 ... %}
    """
    bits = token.split_contents()
    additions, removals = [], []
    try:
        filterchain_var = bits[1]
    except IndexError:
        raise template.TemplateSyntaxError(
            'Missing required filterchain argument')
    # TODO: This probably fails for removals of hard-coded strings that contain spaces.
    bits = bits[2:]
    clear = False
    while bits:
        bit = bits.pop(0)
        if bit.startswith('-'):
            key = bit[1:]
            if not len(key):
                raise template.TemplateSyntaxError('Invalid argument: %r' %
                                                   bit)
            if key == 'all':
                removals = []
                clear = True
            else:
                removals.append(key)
        elif bit.startswith('+'):
            key = bit[1:]
            if not len(key):
                raise template.TemplateSyntaxError('Invalid argument: %r' %
                                                   bit)
            values = []
            while bits:
                # Consume all remaining args until the next addition/removal.
                if bits[0][0] in ('+', '-'):
                    break
                values.append(bits.pop(0))
            # if not len(values):
            #     raise template.TemplateSyntaxError('Invalid argument: %r' % bit)
            additions.append((key, values))
        else:
            raise template.TemplateSyntaxError('Invalid argument: %r' % bit)
    return FilterUrlNode(filterchain_var, additions, removals, clear=clear)
Exemplo n.º 12
0
def do_get_articles_latest(parser, token):
    bits = token.split_contents()
    if len(bits) != 4:
        raise template.TemplateSyntaxError(
            "'get_last_articles' tag takes exactly 4 arguments")
    return ArticlesLatestNode(bits[2], bits[3])
Exemplo n.º 13
0
def do_get_first_paragraph(parser, token):
    bits = token.split_contents()
    if len(bits) != 4:
        raise template.TemplateSyntaxError(
            "'get_first_paragraph' tag takes exactly 4 arguments")
    return FirstParagraphNode(bits[2], bits[3])
Exemplo n.º 14
0
def primary_group_avatar_object(parser, token):
    split = token.split_contents()
    if len(split) == 4:
        return GroupAvatarObjectNode(split[1], split[3])
    else:
        raise template.TemplateSyntaxError('%r tag takes three arguments.' % split[0])
Exemplo n.º 15
0
 def handle_token(cls, parser, token):
     bits = token.split_contents()
     if len(bits) == 3 and bits[1] == "as":
         return cls(bits[2])
     else:
         raise template.TemplateSyntaxError("%r takes 'as var'" % bits[0])
Exemplo n.º 16
0
def dateAdvance(parse, token):
    try:
        tag_name, fromat_string = token.split_contents()
    except ValueError:
        raise template.TemplateSyntaxError('invalid args')
    return DateNode(fromat_string[1:-1])
Exemplo n.º 17
0
def do_recover_tweets(parser, token):
    try:
        tag_name = token.split_contents()
    except ValueError:
        raise template.TemplateSyntaxError('%r tag requires zero arguments' % token.contents.split()[0])
    return RecoverTweetsNode()
Exemplo n.º 18
0
 def error():
     raise template.TemplateSyntaxError(
         fnctl + "accepts the syntax: {%%" + fnctl +
         " [start,] stop[, step] as context_name %%}," +
         " where 'start', 'stop' and 'step' must all be integers.")
Exemplo n.º 19
0
 def __init__(self, varname=None, name=None):
     if name is None:
         raise template.TemplateSyntaxError(
             "Prefix nodes must be given a name to return.")
     self.varname = varname
     self.name = name
def facebook_configured(parser, token):
    bits = token.split_contents()
    if len(bits) != 3:
        raise template.TemplateSyntaxError('%s takes one arg' % bits[0])
    return FacebookConfiguredNode(bits[2])
Exemplo n.º 21
0
def cropped_thumbnail(context, instance, ratiofieldname, **kwargs):
    '''
    Syntax:
    {% cropped_thumbnail instancename "ratiofieldname"
        [scale=0.1|width=100|height=200|max_size="100x200"] [upscale=True] %}
    '''

    ratiofield = instance._meta.get_field(ratiofieldname)
    image = getattr(instance, ratiofield.image_field)  # get imagefield
    if ratiofield.image_fk_field:  # image is ForeignKey
        # get the imagefield
        image = getattr(image, ratiofield.image_fk_field)

    if not image:
        return

    box = getattr(instance, ratiofieldname)
    if ratiofield.free_crop:
        if not box:
            size = (image.width, image.height)
        else:
            box_values = list(map(int, box.split(',')))
            size = (box_values[2] - box_values[0],
                    box_values[3] - box_values[1])
    else:
        size = (int(ratiofield.width), int(ratiofield.height))

    if sum(k in kwargs for k in VALID_OPTIONS) > 1:
        raise template.TemplateSyntaxError(
            'Only one size modifier is allowed.')

    if 'scale' in kwargs:
        width = size[0] * kwargs['scale']
        height = size[1] * kwargs['scale']
    elif 'width' in kwargs:
        width = kwargs['width']
        height = size[1] * width / size[0]
    elif 'height' in kwargs:
        height = kwargs['height']
        width = height * size[0] / size[1]
    elif 'max_size' in kwargs:
        try:
            max_width, max_height = list(
                map(int, kwargs['max_size'].split('x')))
        except (ValueError, AttributeError):
            raise template.TemplateSyntaxError("max_size must match INTxINT")

        width, height = size
        # recalculate height if needed
        if max_width < width:
            height = height * max_width / width
            width = max_width
        # recalculate width if needed
        if max_height < height:
            width = max_height * width / height
            height = max_height

    if any(k in kwargs for k in VALID_OPTIONS):
        # adjust size based on given modifier
        size = (int(width), int(height))

    if ratiofield.adapt_rotation:
        if (image.height > image.width) != (size[1] > size[0]):
            # box needs rotation
            size = (size[1], size[0])

    thumbnailer = get_thumbnailer(image)
    thumbnail_options = {
        'size': size,
        'box': box,
        'crop': True,
        'detail': kwargs.pop('detail', True),
        'upscale': kwargs.pop('upscale', False)
    }
    # remove all cropping kwargs
    for k in VALID_OPTIONS:
        kwargs.pop(k, None)
    # pass remaining arguments to easy_thumbnail
    thumbnail_options.update(kwargs)

    return thumbnailer.get_thumbnail(thumbnail_options).url
def set_comment_remove_variable(parser, token):
    args = token.split_contents()
    if not len(args) in [4, 6]:
        raise template.TemplateSyntaxError("Not the right amount of args")

    return RemoveCommentNode(args[2], args[3], args[5])
Exemplo n.º 23
0
def google_static_map(parser, token):
	try:
		tag_name, event, width, height, zoom = token.split_contents()
	except ValueError:
		raise template.TemplateSyntaxError('google_static_map requires an event, width, height and zoom level')
	return GoogleStaticMapNode(event, width, height, zoom)
Exemplo n.º 24
0
def stripe_payment(parser, token):
    try:
        tag, int_obj = token.split_contents()
    except ValueError:
        raise template.TemplateSyntaxError("%r was expecting a single argument" %token.split_contents()[0])
    return StripeNode(int_obj)
Exemplo n.º 25
0
def do_switch(parser, token):
    """
    The ``{% switch %}`` tag compares a variable against one or more values in
    ``{% case %}`` tags, and outputs the contents of the matching block.  An
    optional ``{% else %}`` tag sets off the default output if no matches
    could be found::

        {% switch result_count %}
            {% case 0 %}
                There are no search results.
            {% case 1 %}
                There is one search result.
            {% else %}
                Jackpot! Your search found {{ result_count }} results.
        {% endswitch %}

    Each ``{% case %}`` tag can take multiple values to compare the variable
    against::

        {% switch username %}
            {% case "Jim" "Bob" "Joe" %}
                Me old mate {{ username }}! How ya doin?
            {% else %}
                Hello {{ username }}
        {% endswitch %}
    """
    bits = token.contents.split()
    tag_name = bits[0]
    if len(bits) != 2:
        raise template.TemplateSyntaxError("'%s' tag requires one argument" % tag_name)
    variable = parser.compile_filter(bits[1])

    class BlockTagList(object):
        # This is a bit of a hack, as it embeds knowledge of the behaviour
        # of Parser.parse() relating to the "parse_until" argument.
        def __init__(self, *names):
            self.names = set(names)
        def __contains__(self, token_contents):
            name = token_contents.split()[0]
            return name in self.names

    # Skip over everything before the first {% case %} tag
    parser.parse(BlockTagList('case', 'endswitch'))

    cases = []
    token = parser.next_token()
    got_case = False
    got_else = False
    while token.contents != 'endswitch':
        nodelist = parser.parse(BlockTagList('case', 'else', 'endswitch'))
        
        if got_else:
            raise template.TemplateSyntaxError("'else' must be last tag in '%s'." % tag_name)

        contents = token.contents.split()
        token_name, token_args = contents[0], contents[1:]
        
        if token_name == 'case':
            tests = map(parser.compile_filter, token_args)
            case = (tests, nodelist)
            got_case = True
        else:
            # The {% else %} tag
            case = (None, nodelist)
            got_else = True
        cases.append(case)
        token = parser.next_token()
 def compiler(parser, token):
     args, kwargs, alias = parse_token(parser, token)
     if not alias:
         raise template.TemplateSyntaxError("Alias not provided for assignment_tag")
     return CompatibilityNode(takes_context, func, args, kwargs, alias)
Exemplo n.º 27
0
def show_current_number(parser, token):
    """Show the current page number, or insert it in the context.

    This tag can for example be useful to change the page title according to
    the current page number.

    To just show current page number:

    .. code-block:: html+django

        {% show_current_number %}

    If you use multiple paginations in the same page, you can get the page
    number for a specific pagination using the querystring key, e.g.:

    .. code-block:: html+django

        {% show_current_number using mykey %}

    The default page when no querystring is specified is 1. If you changed it
    in the `paginate`_ template tag, you have to call  ``show_current_number``
    according to your choice, e.g.:

    .. code-block:: html+django

        {% show_current_number starting from page 3 %}

    This can be also achieved using a template variable you passed to the
    context, e.g.:

    .. code-block:: html+django

        {% show_current_number starting from page page_number %}

    You can of course mix it all (the order of arguments is important):

    .. code-block:: html+django

        {% show_current_number starting from page 3 using mykey %}

    If you want to insert the current page number in the context, without
    actually displaying it in the template, use the *as* argument, i.e.:

    .. code-block:: html+django

        {% show_current_number as page_number %}
        {% show_current_number
            starting from page 3 using mykey as page_number %}

    """
    # Validate args.
    try:
        tag_name, args = token.contents.split(None, 1)
    except ValueError:
        key = None
        number = None
        tag_name = token.contents[0]
        var_name = None
    else:
        # Use a regexp to catch args.
        match = SHOW_CURRENT_NUMBER_EXPRESSION.match(args)
        if match is None:
            msg = 'Invalid arguments for %r tag' % tag_name
            raise template.TemplateSyntaxError(msg)
        # Retrieve objects.
        groupdict = match.groupdict()
        key = groupdict['key']
        number = groupdict['number']
        var_name = groupdict['var_name']
    # Call the node.
    return ShowCurrentNumberNode(number, key, var_name)
 def compiler(parser, token):
     args, kwargs, alias = parse_token(parser, token)
     if alias:
         raise template.TemplateSyntaxError("Alias not allowed for simple_tag")
     return CompatibilityNode(takes_context, func, args, kwargs, alias)
Exemplo n.º 29
0
def paginate(parser, token, paginator_class=None):
    """Paginate objects.

    Usage:

    .. code-block:: html+django

        {% paginate entries %}

    After this call, the *entries* variable in the template context is replaced
    by only the entries of the current page.

    You can also keep your *entries* original variable (usually a queryset)
    and add to the context another name that refers to entries of the current
    page, e.g.:

    .. code-block:: html+django

        {% paginate entries as page_entries %}

    The *as* argument is also useful when a nested context variable is provided
    as queryset. In this case, and only in this case, the resulting variable
    name is mandatory, e.g.:

    .. code-block:: html+django

        {% paginate entries.all as entries %}

    The number of paginated entries is taken from settings, but you can
    override the default locally, e.g.:

    .. code-block:: html+django

        {% paginate 20 entries %}

    Of course you can mix it all:

    .. code-block:: html+django

        {% paginate 20 entries as paginated_entries %}

    By default, the first page is displayed the first time you load the page,
    but you can change this, e.g.:

    .. code-block:: html+django

        {% paginate entries starting from page 3 %}

    When changing the default page, it is also possible to reference the last
    page (or the second last page, and so on) by using negative indexes, e.g:

    .. code-block:: html+django

        {% paginate entries starting from page -1 %}

    This can be also achieved using a template variable that was passed to the
    context, e.g.:

    .. code-block:: html+django

        {% paginate entries starting from page page_number %}

    If the passed page number does not exist, the first page is displayed.

    If you have multiple paginations in the same page, you can change the
    querydict key for the single pagination, e.g.:

    .. code-block:: html+django

        {% paginate entries using article_page %}

    In this case *article_page* is intended to be a context variable, but you
    can hardcode the key using quotes, e.g.:

    .. code-block:: html+django

        {% paginate entries using 'articles_at_page' %}

    Again, you can mix it all (the order of arguments is important):

    .. code-block:: html+django

        {% paginate 20 entries
            starting from page 3 using page_key as paginated_entries %}

    Additionally you can pass a path to be used for the pagination:

    .. code-block:: html+django

        {% paginate 20 entries
            using page_key with pagination_url as paginated_entries %}

    This way you can easily create views acting as API endpoints, and point
    your Ajax calls to that API. In this case *pagination_url* is considered a
    context variable, but it is also possible to hardcode the URL, e.g.:

    .. code-block:: html+django

        {% paginate 20 entries with "/mypage/" %}

    If you want the first page to contain a different number of items than
    subsequent pages, you can separate the two values with a comma, e.g. if
    you want 3 items on the first page and 10 on other pages:

    .. code-block:: html+django

    {% paginate 3,10 entries %}

    You must use this tag before calling the {% show_more %} one.
    """
    # Validate arguments.
    try:
        tag_name, tag_args = token.contents.split(None, 1)
    except ValueError:
        msg = '%r tag requires arguments' % token.contents.split()[0]
        raise template.TemplateSyntaxError(msg)

    # Use a regexp to catch args.
    match = PAGINATE_EXPRESSION.match(tag_args)
    if match is None:
        msg = 'Invalid arguments for %r tag' % tag_name
        raise template.TemplateSyntaxError(msg)

    # Retrieve objects.
    kwargs = match.groupdict()
    objects = kwargs.pop('objects')

    # The variable name must be present if a nested context variable is passed.
    if '.' in objects and kwargs['var_name'] is None:
        msg = (
            '%(tag)r tag requires a variable name `as` argumnent if the '
            'queryset is provided as a nested context variable (%(objects)s). '
            'You must either pass a direct queryset (e.g. taking advantage '
            'of the `with` template tag) or provide a new variable name to '
            'store the resulting queryset (e.g. `%(tag)s %(objects)s as '
            'objects`).') % {
                'tag': tag_name,
                'objects': objects
            }
        raise template.TemplateSyntaxError(msg)

    # Call the node.
    return PaginateNode(paginator_class, objects, **kwargs)
Exemplo n.º 30
0
def filmod(value, arg):
    try:
        return int(value) % int(arg)
    except ValueError:
        raise template.TemplateSyntaxError('mod requires integer arguments')