import re
from functools import wraps
import json
import django
from django import template
from django.apps import apps
from django.conf import settings
from django.contrib.admin.options import InlineModelAdmin
from django.utils.safestring import mark_safe
from django.utils.html import escape
register = template.Library()
if django.VERSION >= (1, 10):
from django.templatetags.static import static as _static
else:
_static = None
django_version = django.VERSION[:2]
[docs]@register.simple_tag
def static(path):
global _static
if _static is None:
if apps.is_installed('django-contrib.staticfiles'):
from django.contrib.staticfiles.templatetags.staticfiles import static as _static
else:
from django.templatetags.static import static as _static
if django.VERSION >= (1, 9) and path == 'admin/img/icon-unknown.gif':
path = 'admin/img/icon-unknown.svg'
return _static(path)
[docs]@register.filter
def strip_parent_name(nested_name, parent_name):
if nested_name.find(parent_name + " ") == 0:
return nested_name[len(parent_name)+1:]
else:
return nested_name
strip_parent_name.is_safe = True
# These tags are defined in grappelli.templatetags.grp_tags. The issue is that
# they are wrapped in mark_safe(), so we can't use them reliably inside of
# attributes.
[docs]@register.filter
def json_encode(data):
return escape(json.dumps(data))
[docs]def json_else_list_tag(f):
"""
Decorator. Registers function as a simple_tag.
Try: Return value of the decorated function json encoded.
Except: Return []
"""
@wraps(f)
def inner(model_admin):
try:
return mark_safe(escape(json.dumps(f(model_admin))))
except:
return []
return register.simple_tag(inner)
# AUTOCOMPLETES
[docs]@json_else_list_tag
def get_safe_autocomplete_lookup_fields_fk(model_admin):
return model_admin.autocomplete_lookup_fields.get("fk", [])
[docs]@json_else_list_tag
def get_safe_autocomplete_lookup_fields_m2m(model_admin):
return model_admin.autocomplete_lookup_fields.get("m2m", [])
[docs]@json_else_list_tag
def get_safe_autocomplete_lookup_fields_generic(model_admin):
return model_admin.autocomplete_lookup_fields.get("generic", [])
[docs]@register.filter
def cell_count(inline_admin_form):
"""Returns the number of cells used in a tabular inline"""
count = 1 # Hidden cell with hidden 'id' field
for fieldset in inline_admin_form:
# Loop through all the fields (one per cell)
for line in fieldset:
for field in line:
count += 1
if inline_admin_form.formset.can_delete:
# Delete checkbox
count += 1
return count
[docs]class IfConditionNode(template.Node):
def __init__(self, nodelist_true, nodelist_false, value):
self.nodelist_true = nodelist_true
self.nodelist_false = nodelist_false
self.value = value
[docs] def render(self, context):
if self.value:
return self.nodelist_true.render(context)
else:
return self.nodelist_false.render(context)
[docs]def str_to_version(string):
return tuple([int(s) for s in string.split('.')])
[docs]@register.filter
def django_version_lt(string):
return django_version < str_to_version(string)
[docs]@register.filter
def django_version_lte(string):
return django_version <= str_to_version(string)
[docs]@register.filter
def django_version_gt(string):
return django_version > str_to_version(string)
[docs]@register.filter
def django_version_gte(string):
return django_version >= str_to_version(string)
[docs]@register.tag
def ifinlineclasses(parser, token):
nodelist_true = parser.parse(('else', 'endifinlineclasses'))
token = parser.next_token()
if token.contents == 'else':
nodelist_false = parser.parse(('endifinlineclasses',))
parser.delete_first_token()
else:
nodelist_false = template.NodeList()
return IfConditionNode(nodelist_true, nodelist_false, hasattr(InlineModelAdmin, 'classes'))
[docs]@register.tag
def ifsuit(parser, token):
nodelist_true = parser.parse(('else', 'endifsuit'))
token = parser.next_token()
if token.contents == 'else':
nodelist_false = parser.parse(('endifsuit',))
parser.delete_first_token()
else:
nodelist_false = template.NodeList()
return IfConditionNode(nodelist_true, nodelist_false, 'suit' in settings.INSTALLED_APPS)
[docs]@register.tag
def ifnotsuit(parser, token):
nodelist_true = parser.parse(('else', 'endifnotsuit'))
token = parser.next_token()
if token.contents == 'else':
nodelist_false = parser.parse(('endifnotsuit',))
parser.delete_first_token()
else:
nodelist_false = template.NodeList()
return IfConditionNode(nodelist_true, nodelist_false, 'suit' not in settings.INSTALLED_APPS)