Source code for django_webix.templatetags.django_webix_utils

# -*- coding: utf-8 -*-

import datetime
import re

import six
from django import template
from django.apps import apps
from django.conf import settings
from django.template import TemplateSyntaxError
from django.utils.timezone import is_naive, make_naive

try:
    from django.template.base import TokenType
except ImportError:
    # Django < 2.1
    from django.template.base import TOKEN_BLOCK
else:
    TOKEN_BLOCK = TokenType.BLOCK

from django.template.defaulttags import (CommentNode, IfNode, LoadNode,
                                         find_library, load_from_library)
from django.template.smartif import Literal

register = template.Library()


[docs]@register.filter('get_value_from_dict') def get_value_from_dict(dict_data, key): """ usage example {{ your_dict|get_value_from_dict:your_key }} """ if key: return dict_data.get(key)
@register.simple_tag(name='webix_version') def webix_version(): return settings.WEBIX_VERSION @register.simple_tag(name='webix_license') def webix_license(): return settings.WEBIX_LICENSE @register.simple_tag(name='is_installed_djangowebixleaflet') def is_installed_djangowebixleaflet(): return apps.is_installed("django_webix_leaflet") @register.simple_tag(name='is_installed_djangowebixfilter') def is_installed_djangowebixfilter(): return apps.is_installed("webix_filter") @register.simple_tag(name='webix_history_enable') def webix_history_enable(): if hasattr(settings, 'WEBIX_HISTORY_ENABLE'): return settings.WEBIX_HISTORY_ENABLE else: return False @register.simple_tag(name='webix_fontawesome_css_url') def webix_fontawesome_css_url(): if hasattr(settings, 'WEBIX_FONTAWESOME_CSS_URL'): return settings.WEBIX_FONTAWESOME_CSS_URL else: return 'django_webix/fontawesome-5.7.2/css/all.min.css' @register.simple_tag(name='webix_fontawesome_version') def webix_fontawesome_version(): if hasattr(settings, 'WEBIX_FONTAWESOME_VERSION'): return settings.WEBIX_FONTAWESOME_VERSION else: return '5.7.2' @register.filter def comma_to_underscore(value): return value.replace(".", "_") @register.filter_function def order_by(queryset, args): args = [x.strip() for x in args.split(',')] return queryset.order_by(*args) @register.filter def format_list_value(value): if type(value) == datetime.date: return value.strftime('%d/%m/%Y') elif type(value) == datetime.datetime: if not is_naive(value): value = make_naive(value) return value.strftime('%d/%m/%Y %H:%M') elif value is None: return '' return str(value)
[docs]@register.filter def getattr(obj, args): """ Try to get an attribute from an object. Example: {% if block|getattr:"editable,True" %} Beware that the default is always a string, if you want this to return False, pass an empty second argument: {% if block|getattr:"editable," %} """ splitargs = args.split(',') try: (attribute, default) = splitargs except ValueError: (attribute, default) = args, '' if isinstance(obj, six.string_types): return obj try: attr = obj.__getattribute__(attribute) except AttributeError: attr = obj.__dict__.get(attribute, default) except Exception: attr = default if hasattr(attr, '__call__'): return attr.__call__() else: return attr
class SetVarNode(template.Node): def __init__(self, new_val, var_name): self.new_val = new_val self.var_name = var_name def render(self, context): context[self.var_name] = self.new_val return '' @register.tag def setvar(parser, token): # This version uses a regular expression to parse tag contents. try: # Splitting by None == splitting by spaces. tag_name, arg = token.contents.split(None, 1) except ValueError: raise template.TemplateSyntaxError("%r tag requires arguments" % token.contents.split()[0]) m = re.search(r'(.*?) as (\w+)', arg) if not m: raise template.TemplateSyntaxError("%r tag had invalid arguments" % tag_name) new_val, var_name = m.groups() if not (new_val[0] == new_val[-1] and new_val[0] in ('"', "'")): raise template.TemplateSyntaxError("%r tag's argument should be in quotes" % tag_name) return SetVarNode(new_val[1:-1], var_name)
[docs]@register.tag def friendly_load(parser, token): """ Tries to load a custom template tag set. Non existing tag libraries are ignored. This means that, if used in conjunction with ``if_has_tag``, you can try to load the comments template tag library to enable comments even if the comments framework is not installed. For example:: {% load friendly_loader %} {% friendly_load comments webdesign %} {% if_has_tag render_comment_list %} {% render_comment_list for obj %} {% else %} {% if_has_tag lorem %} {% lorem %} {% endif_has_tag %} {% endif_has_tag %} """ bits = token.contents.split() if len(bits) >= 4 and bits[-2] == "from": # from syntax is used; load individual tags from the library name = bits[-1] try: lib = find_library(parser, name) subset = load_from_library(lib, name, bits[1:-2]) parser.add_library(subset) except TemplateSyntaxError: pass else: # one or more libraries are specified; load and add them to the parser for name in bits[1:]: try: lib = find_library(parser, name) parser.add_library(lib) except TemplateSyntaxError: pass return LoadNode()
[docs]def do_if_has_tag(parser, token, negate=False): """ The logic for both ``{% if_has_tag %}`` and ``{% if not_has_tag %}``. Checks if all the given tags exist (or not exist if ``negate`` is ``True``) and then only parses the branch that will not error due to non-existing tags. This means that the following is essentially the same as a ``{% comment %}`` tag:: {% if_has_tag non_existing_tag %} {% non_existing_tag %} {% endif_has_tag %} Another example is checking a built-in tag. This will always render the current year and never FAIL:: {% if_has_tag now %} {% now "Y" %} {% else %} FAIL {% endif_has_tag %} """ bits = list(token.split_contents()) if len(bits) < 2: raise TemplateSyntaxError("%r takes at least one arguments" % bits[0]) end_tag = 'end%s' % bits[0] has_tag = all([tag in parser.tags for tag in bits[1:]]) has_tag = (not negate and has_tag) or (negate and not has_tag) nodelist_true = nodelist_false = CommentNode() if has_tag: nodelist_true = parser.parse(('else', end_tag)) token = parser.next_token() if token.contents == 'else': parser.skip_past(end_tag) else: while parser.tokens: token = parser.next_token() if token.token_type == TOKEN_BLOCK and token.contents == end_tag: return IfNode([ (Literal(has_tag), nodelist_true), (None, nodelist_false) ]) elif token.token_type == TOKEN_BLOCK and token.contents == 'else': break nodelist_false = parser.parse((end_tag,)) parser.next_token() return IfNode([(Literal(has_tag), nodelist_true), (None, nodelist_false)])
[docs]@register.tag def if_has_tag(parser, token): """ Do something if all given tags are loaded:: {% load friendly_loader %} {% friendly_load webdesign %} {% if_has_tag lorem %} {% lorem %} {% else %} Non dummy content goes here! {% endif_has_tag %} When given multiple arguments each and every tag in the list has to be available. This means that the following will render nothing:: {% if_has_tag now nonexisting_tag %} {% now "Y" %} {% endif_has_tag %} """ return do_if_has_tag(parser, token)
[docs]@register.tag def ifnot_has_tag(parser, token): """ Do something unless any given tag is loaded:: {% load friendly_loader %} {% friendly_load comments %} {% ifnot_has_tag render_comment_list %} Comment support has been disabled. {% else %} {% render_comment_list for obj %} {% endifnot_has_tag %} In the case of multiple arguments, the condition will trigger if any tag in the list is unavailable. This means that the following will still render the current year:: {% ifnot_has_tag now nonexisting_tag %} {% now "Y" %} {% endifnot_has_tag %} """ return do_if_has_tag(parser, token, True)