diff --git a/django_tables2/columns/templatecolumn.py b/django_tables2/columns/templatecolumn.py index ddddc24a..2bb9f69b 100644 --- a/django_tables2/columns/templatecolumn.py +++ b/django_tables2/columns/templatecolumn.py @@ -2,6 +2,7 @@ from django.template.loader import get_template from django.utils.html import strip_tags +from ..utils import call_with_appropriate from .base import Column, library @@ -14,7 +15,9 @@ class TemplateColumn(Column): Arguments: template_code (str): template code to render template_name (str): name of the template to render - extra_context (dict): optional extra template context + context_object_name (str): name of the context variable to pas the record in, defaults to "record". + extra_context (dict): optional extra template context. If a callable is passed, it will be called with + optional record, table, value, bound_column arguments. A `~django.template.Template` object is created from the *template_code* or *template_name* and rendered with a context containing: @@ -40,11 +43,19 @@ class ExampleTable(tables.Table): empty_values = () - def __init__(self, template_code=None, template_name=None, extra_context=None, **extra): + def __init__( + self, + template_code=None, + template_name=None, + context_object_name="record", + extra_context=None, + **extra + ): super().__init__(**extra) self.template_code = template_code self.template_name = template_name self.extra_context = extra_context or {} + self.context_object_name = context_object_name if not self.template_code and not self.template_name: raise ValueError("A template must be provided") @@ -56,11 +67,18 @@ def render(self, record, table, value, bound_column, **kwargs): additional_context = { "default": bound_column.default, "column": bound_column, - "record": record, + self.context_object_name: record, "value": value, "row_counter": kwargs["bound_row"].row_counter, } - additional_context.update(self.extra_context) + + extra_context = self.extra_context + if callable(extra_context): + extra_context = call_with_appropriate( + extra_context, + {"record": record, "table": table, "value": value, "bound_column": bound_column}, + ) + additional_context.update(extra_context) with context.update(additional_context): if self.template_code: return Template(self.template_code).render(context) diff --git a/tests/columns/test_templatecolumn.py b/tests/columns/test_templatecolumn.py index 643ab3cb..414fead7 100644 --- a/tests/columns/test_templatecolumn.py +++ b/tests/columns/test_templatecolumn.py @@ -115,3 +115,19 @@ class Table(tables.Table): table = Table([{"track": "Space Oddity"}]) self.assertEqual(list(table.as_values()), [["Track"], ["Space Oddity"]]) + + def test_context_object_name(self): + class Table(tables.Table): + name = tables.TemplateColumn("{{ user.name }}", context_object_name="user") + + table = Table([{"name": "Bob"}]) + self.assertEqual(list(table.as_values()), [["Name"], ["Bob"]]) + + def test_extra_context_callable(self): + class Table(tables.Table): + size = tables.TemplateColumn( + "{{ size }}", extra_context=lambda record: {"size": record["clothes"]["size"]} + ) + + table = Table([{"clothes": {"size": "XL"}}]) + self.assertEqual(list(table.as_values()), [["Size"], ["XL"]])