File: templatecolumn.py

package info (click to toggle)
django-tables 2.7.5-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 1,752 kB
  • sloc: python: 7,120; makefile: 132; sh: 74
file content (77 lines) | stat: -rw-r--r-- 3,061 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
from django.template import Context, Template
from django.template.loader import get_template
from django.utils.html import strip_tags

from .base import Column, library


@library.register
class TemplateColumn(Column):
    """
    A subclass of `.Column` that renders some template code to use as
    the cell value.

    Arguments:
        template_code (str): template code to render
        template_name (str): name of the template to render
        extra_context (dict): optional extra template context

    A `~django.template.Template` object is created from the
    *template_code* or *template_name* and rendered with a context containing:

    - *record*      -- data record for the current row
    - *value*       -- value from `record` that corresponds to the current column
    - *default*     -- appropriate default value to use as fallback.
    - *row_counter* -- The number of the row this cell is being rendered in.
    - any context variables passed using the `extra_context` argument to `TemplateColumn`.

    Example:

    .. code-block:: python

        class ExampleTable(tables.Table):
            foo = tables.TemplateColumn("{{ record.bar }}")
            # contents of `myapp/bar_column.html` is `{{ label }}: {{ value }}`
            bar = tables.TemplateColumn(template_name="myapp/name2_column.html",
                                        extra_context={"label": "Label"})

    Both columns will have the same output.
    """

    empty_values = ()

    def __init__(self, template_code=None, template_name=None, extra_context=None, **extra):
        super().__init__(**extra)
        self.template_code = template_code
        self.template_name = template_name
        self.extra_context = extra_context or {}

        if not self.template_code and not self.template_name:
            raise ValueError("A template must be provided")

    def render(self, record, table, value, bound_column, **kwargs):
        # If the table is being rendered using `render_table`, it hackily
        # attaches the context to the table as a gift to `TemplateColumn`.
        context = getattr(table, "context", Context())
        additional_context = {
            "default": bound_column.default,
            "column": bound_column,
            "record": record,
            "value": value,
            "row_counter": kwargs["bound_row"].row_counter,
        }
        additional_context.update(self.extra_context)
        with context.update(additional_context):
            if self.template_code:
                return Template(self.template_code).render(context)
            else:
                return get_template(self.template_name).render(context.flatten())

    def value(self, **kwargs):
        """
        The value returned from a call to `value()` on a `TemplateColumn` is
        the rendered template with `django.utils.html.strip_tags` applied.
        Leading and trailing whitespace is stripped.
        """
        html = super().value(**kwargs)
        return strip_tags(html).strip() if isinstance(html, str) else html