1from .base import Column, library
2
3
4class BaseLinkColumn(Column):
5    """
6    The base for other columns that render links.
7
8    Arguments:
9        text (str or callable): If set, this value will be used to render the
10            text inside link instead of value. The callable gets the record
11            being rendered as argument.
12        attrs (dict): In addition to ``attrs`` keys supported by `~.Column`, the
13            following are available:
14
15             - `a` -- ``<a>`` in ``<td>`` elements.
16    """
17
18    def __init__(self, text=None, *args, **kwargs):
19        super().__init__(*args, **kwargs)
20        self.text = text
21
22    def text_value(self, record, value):
23        if self.text is None:
24            return value
25        return self.text(record) if callable(self.text) else self.text
26
27    def value(self, record, value):
28        """
29        Returns the content for a specific cell similarly to `.render` however
30        without any html content.
31        """
32        return self.text_value(record, value)
33
34    def render(self, record, value):
35        return self.text_value(record, value)
36
37
38@library.register
39class LinkColumn(BaseLinkColumn):
40    """
41    Renders a normal value as an internal hyperlink to another page.
42
43    .. note ::
44
45        This column should not be used anymore, the `linkify` keyword argument to
46        regular columns can be used to achieve the same results.
47
48    It's common to have the primary value in a row hyperlinked to the page
49    dedicated to that record.
50
51    The first arguments are identical to that of
52    `~django.urls.reverse` and allows an internal URL to be
53    described. If this argument is `None`, then `get_absolute_url`.
54    (see Django references) will be used.
55    The last argument *attrs* allows custom HTML attributes to be added to the
56    rendered ``<a href="...">`` tag.
57
58    Arguments:
59        viewname (str or None): See `~django.urls.reverse`, or use `None`
60            to use the model's `get_absolute_url`
61        urlconf (str): See `~django.urls.reverse`.
62        args (list): See `~django.urls.reverse`. [2]_
63        kwargs (dict): See `~django.urls.reverse`. [2]_
64        current_app (str): See `~django.urls.reverse`.
65        attrs (dict): HTML attributes that are added to the rendered
66            ``<a ...>...</a>`` tag.
67        text (str or callable): Either static text, or a callable. If set, this
68            will be used to render the text inside link instead of value (default).
69            The callable gets the record being rendered as argument.
70
71    .. [2] In order to create a link to a URL that relies on information in the
72        current row, `.Accessor` objects can be used in the *args* or *kwargs*
73        arguments. The accessor will be resolved using the row's record before
74        `~django.urls.reverse` is called.
75
76    Example:
77
78    .. code-block:: python
79
80        # models.py
81        class Person(models.Model):
82            name = models.CharField(max_length=200)
83
84        # urls.py
85        urlpatterns = patterns('',
86            url("people/([0-9]+)/", views.people_detail, name="people_detail")
87        )
88
89        # tables.py
90        from django_tables2.utils import A  # alias for Accessor
91
92        class PeopleTable(tables.Table):
93            name = tables.LinkColumn("people_detail", args=[A("pk")])
94
95    In order to override the text value (i.e. ``<a ... >text</a>``) consider
96    the following example:
97
98    .. code-block:: python
99
100        # tables.py
101        from django_tables2.utils import A  # alias for Accessor
102
103        class PeopleTable(tables.Table):
104            name = tables.LinkColumn("people_detail", text="static text", args=[A("pk")])
105            age  = tables.LinkColumn("people_detail", text=lambda record: record.name, args=[A("pk")])
106
107    In the first example, a static text would be rendered (``"static text"``)
108    In the second example, you can specify a callable which accepts a record object (and thus
109    can return anything from it)
110
111    In addition to *attrs* keys supported by `.Column`, the following are
112    available:
113
114    - `a` -- ``<a>`` elements in ``<td>``.
115
116    Adding attributes to the ``<a>``-tag looks like this::
117
118        class PeopleTable(tables.Table):
119            first_name = tables.LinkColumn(attrs={
120                "a": {"style": "color: red;"}
121            })
122
123    """
124
125    def __init__(
126        self,
127        viewname=None,
128        urlconf=None,
129        args=None,
130        kwargs=None,
131        current_app=None,
132        attrs=None,
133        **extra
134    ):
135        super().__init__(
136            attrs=attrs,
137            linkify=dict(
138                viewname=viewname,
139                urlconf=urlconf,
140                args=args,
141                kwargs=kwargs,
142                current_app=current_app,
143            ),
144            **extra
145        )
146
147
148@library.register
149class RelatedLinkColumn(LinkColumn):
150    """
151    Render a link to a related object using related object's ``get_absolute_url``,
152    same parameters as ``~.LinkColumn``.
153
154    .. note ::
155
156        This column should not be used anymore, the `linkify` keyword argument to
157        regular columns can be used achieve the same results.
158
159    If the related object does not have a method called ``get_absolute_url``,
160    or if it is not callable, the link will be rendered as '#'.
161
162    Traversing relations is also supported, suppose a Person has a foreign key to
163    Country which in turn has a foreign key to Continent::
164
165        class PersonTable(tables.Table):
166            name = tables.Column()
167            country = tables.RelatedLinkColumn()
168            continent = tables.RelatedLinkColumn(accessor="country.continent")
169
170    will render:
171
172     - in column 'country', link to ``person.country.get_absolute_url()`` with the output of
173       ``str(person.country)`` as ``<a>`` contents.
174     - in column 'continent', a link to ``person.country.continent.get_absolute_url()`` with
175       the output of ``str(person.country.continent)`` as ``<a>`` contents.
176
177    Alternative contents of ``<a>`` can be supplied using the ``text`` keyword argument as
178    documented for `~.columns.LinkColumn`.
179    """
180