diff --git a/admin_interface/templates/admin/base_site.html b/admin_interface/templates/admin/base_site.html index 4b4ad14f..dff51a83 100644 --- a/admin_interface/templates/admin/base_site.html +++ b/admin_interface/templates/admin/base_site.html @@ -146,6 +146,9 @@ {% if theme.list_filter_highlight %} list-filter-highlight {% endif %} {% if theme.list_filter_sticky %} list-filter-sticky {% endif %} +{% admin_interface_resolve_variable "adminform" as adminform %} +{% admin_interface_resolve_variable "inline_admin_formsets" as inline_admin_formsets %} + {% if adminform and inline_admin_formsets %} {% admin_interface_use_changeform_tabs adminform inline_admin_formsets as admin_interface_use_changeform_tabs %} {% if admin_interface_use_changeform_tabs %} diff --git a/admin_interface/templatetags/admin_interface_tags.py b/admin_interface/templatetags/admin_interface_tags.py index a675dff1..0fe9df2d 100644 --- a/admin_interface/templatetags/admin_interface_tags.py +++ b/admin_interface/templatetags/admin_interface_tags.py @@ -188,6 +188,23 @@ def admin_interface_use_changeform_tabs(adminform, inline_forms): return has_tabs +@register.simple_tag(takes_context=True) +def admin_interface_resolve_variable(context, var_name, default=""): + bits = var_name.split(".") + current = context.flatten() # merge all and create a context dict + + for bit in bits: + try: + if isinstance(current, dict): + current = current[bit] + else: + current = getattr(current, bit) + except (KeyError, AttributeError, TypeError): + return default + + return template.Variable(var_name).resolve(context) + + @register.filter def admin_interface_slugify(name): return slugify(str(name or "")) diff --git a/tests/test_resolve_variable.py b/tests/test_resolve_variable.py new file mode 100644 index 00000000..15e49413 --- /dev/null +++ b/tests/test_resolve_variable.py @@ -0,0 +1,97 @@ +from django.template import Context, Template +from django.test import SimpleTestCase + + +class ResolveVariableTagTests(SimpleTestCase): + def render_template(self, tpl, context=None): + if context is None: + context = {} + return ( + Template("{% load admin_interface_tags %}" + tpl) + .render(Context(context)) + .strip() + ) + + def test_returns_existing_variable(self): + out = self.render_template( + '{% admin_interface_resolve_variable "myvar" as res %}{{ res }}', + {"myvar": "hello"}, + ) + self.assertEqual(out, "hello") + + def test_returns_default_when_missing(self): + out = self.render_template( + '{% admin_interface_resolve_variable "missingvar" as res %}{{ res }}' + ) + self.assertEqual(out, "") + + def test_returns_custom_default(self): + out = self.render_template( + '{% admin_interface_resolve_variable "missingvar" "def" as res %}{{ res }}' + ) + self.assertEqual(out, "def") + + def test_dotted_variable_existing(self): + context = {"user": {"name": "alice"}} + out = self.render_template( + '{% admin_interface_resolve_variable "user.name" as res %}{{ res }}', + context, + ) + self.assertEqual(out, "alice") + + def test_dotted_variable_missing_middle_key(self): + context = {"user": {}} + out = self.render_template( + '{% admin_interface_resolve_variable "user.name" "def" as res %}{{ res }}', + context, + ) + self.assertEqual(out, "def") + + def test_dotted_variable_missing_top_key(self): + out = self.render_template( + '{% admin_interface_resolve_variable "user.name" "guest" as res %}{{ res }}' + ) + self.assertEqual(out, "guest") + + def test_dotted_variable_with_object_attribute(self): + class User: + def __init__(self): + self.name = "bob" + + context = {"user": User()} + out = self.render_template( + '{% admin_interface_resolve_variable "user.name" as res %}{{ res }}', + context, + ) + self.assertEqual(out, "bob") + + def test_dotted_variable_partial_attribute_missing(self): + class User: + pass + + context = {"user": User()} + out = self.render_template( + '{% admin_interface_resolve_variable "user.name" as res %}{{ res }}', + context, + ) + self.assertEqual(out, "") + + def test_non_dict_non_object_root(self): + context = {"user": "notadict"} + out = self.render_template( + '{% admin_interface_resolve_variable "user.name" as res %}{{ res }}', + context, + ) + self.assertEqual(out, "") + + def test_dotted_variable_object_with_nested_dict(self): + class User: + def __init__(self): + self.info = {"name": "bob"} + + context = {"user": User()} + out = self.render_template( + '{% admin_interface_resolve_variable "user.info.name" as res %}{{ res }}', + context, + ) + self.assertEqual(out, "bob")