From 012f68ed4786c8826f7638ba9693d406b631a72a Mon Sep 17 00:00:00 2001 From: Jan Pieter Waagmeester Date: Wed, 6 Nov 2024 10:39:24 +0100 Subject: [PATCH] More typing, remove RelatedLinkColumn --- django_tables2/__init__.py | 2 -- django_tables2/columns/__init__.py | 3 +-- django_tables2/columns/datetimecolumn.py | 4 ++- django_tables2/columns/emailcolumn.py | 6 +++-- django_tables2/columns/filecolumn.py | 6 +++-- django_tables2/columns/jsoncolumn.py | 24 ++++++----------- django_tables2/columns/linkcolumn.py | 34 ------------------------ docs/pages/api-reference.rst | 6 ----- docs/pages/builtin-columns.rst | 1 - example/app/tables.py | 2 +- tests/columns/test_linkcolumn.py | 25 +---------------- tests/test_extra_columns.py | 2 +- 12 files changed, 23 insertions(+), 92 deletions(-) diff --git a/django_tables2/__init__.py b/django_tables2/__init__.py index 991db711..9b8658da 100644 --- a/django_tables2/__init__.py +++ b/django_tables2/__init__.py @@ -9,7 +9,6 @@ JSONColumn, LinkColumn, ManyToManyColumn, - RelatedLinkColumn, TemplateColumn, TimeColumn, URLColumn, @@ -35,7 +34,6 @@ "JSONColumn", "LinkColumn", "ManyToManyColumn", - "RelatedLinkColumn", "TemplateColumn", "TimeColumn", "URLColumn", diff --git a/django_tables2/columns/__init__.py b/django_tables2/columns/__init__.py index 649d4478..306b432d 100644 --- a/django_tables2/columns/__init__.py +++ b/django_tables2/columns/__init__.py @@ -6,7 +6,7 @@ from .emailcolumn import EmailColumn from .filecolumn import FileColumn from .jsoncolumn import JSONColumn -from .linkcolumn import LinkColumn, RelatedLinkColumn +from .linkcolumn import LinkColumn from .manytomanycolumn import ManyToManyColumn from .templatecolumn import TemplateColumn from .timecolumn import TimeColumn @@ -26,7 +26,6 @@ "JSONColumn", "LinkColumn", "ManyToManyColumn", - "RelatedLinkColumn", "TemplateColumn", "URLColumn", "TimeColumn", diff --git a/django_tables2/columns/datetimecolumn.py b/django_tables2/columns/datetimecolumn.py index 097735e5..b881b086 100644 --- a/django_tables2/columns/datetimecolumn.py +++ b/django_tables2/columns/datetimecolumn.py @@ -1,3 +1,5 @@ +from typing import Self + from django.db import models from .base import library @@ -23,6 +25,6 @@ def __init__(self, format=None, short=True, *args, **kwargs): super().__init__(template_code=template, *args, **kwargs) @classmethod - def from_field(cls, field, **kwargs): + def from_field(cls, field, **kwargs) -> Self | None: if isinstance(field, models.DateTimeField): return cls(**kwargs) diff --git a/django_tables2/columns/emailcolumn.py b/django_tables2/columns/emailcolumn.py index 16561517..05820307 100644 --- a/django_tables2/columns/emailcolumn.py +++ b/django_tables2/columns/emailcolumn.py @@ -1,3 +1,5 @@ +from typing import Self + from django.db import models from .base import library @@ -31,10 +33,10 @@ class PeopleTable(tables.Table): # [...]email@example.com """ - def get_url(self, value): + def get_url(self, value) -> str: return f"mailto:{value}" @classmethod - def from_field(cls, field, **kwargs): + def from_field(cls, field, **kwargs) -> Self | None: if isinstance(field, models.EmailField): return cls(**kwargs) diff --git a/django_tables2/columns/filecolumn.py b/django_tables2/columns/filecolumn.py index 930f6ad3..5dc2f649 100644 --- a/django_tables2/columns/filecolumn.py +++ b/django_tables2/columns/filecolumn.py @@ -1,7 +1,9 @@ import os +from typing import Self from django.db import models from django.utils.html import format_html +from django.utils.safestring import SafeString from ..utils import AttributeDict from .base import library @@ -50,7 +52,7 @@ def text_value(self, record, value): return os.path.basename(value.name) return super().text_value(record, value) - def render(self, record, value): + def render(self, record, value) -> SafeString: attrs = AttributeDict(self.attrs.get("span", {})) classes = [c for c in attrs.get("class", "").split(" ") if c] @@ -80,6 +82,6 @@ def render(self, record, value): ) @classmethod - def from_field(cls, field, **kwargs): + def from_field(cls, field, **kwargs) -> Self | None: if isinstance(field, models.FileField): return cls(**kwargs) diff --git a/django_tables2/columns/jsoncolumn.py b/django_tables2/columns/jsoncolumn.py index e2ae2bc5..54e5a6af 100644 --- a/django_tables2/columns/jsoncolumn.py +++ b/django_tables2/columns/jsoncolumn.py @@ -1,7 +1,9 @@ import json +from typing import Self from django.db.models import JSONField from django.utils.html import format_html +from django.utils.safestring import SafeString from ..utils import AttributeDict from .base import library @@ -9,12 +11,9 @@ try: from django.contrib.postgres.fields import HStoreField - - POSTGRES_AVAILABLE = True except ImportError: - # psycopg2 is not available, cannot import from django.contrib.postgres. - # JSONColumn might still be useful to add manually. - POSTGRES_AVAILABLE = False + # psycopg is not available, cannot import from django.contrib.postgres. + HStoreField = object() @library.register @@ -25,12 +24,6 @@ class JSONColumn(BaseLinkColumn): .. versionadded :: 1.5.0 - .. note:: - - Automatic rendering of data to this column requires PostgreSQL support - (psycopg2 installed) to import the fields, but this column can also be - used manually without it. - Arguments: json_dumps_kwargs: kwargs passed to `json.dumps`, defaults to `{'indent': 2}` attrs (dict): In addition to *attrs* keys supported by `~.Column`, the @@ -47,7 +40,7 @@ def __init__(self, json_dumps_kwargs=None, **kwargs): super().__init__(**kwargs) - def render(self, record, value): + def render(self, record, value) -> SafeString: return format_html( "
{}
", AttributeDict(self.attrs.get("pre", {})).as_html(), @@ -55,7 +48,6 @@ def render(self, record, value): ) @classmethod - def from_field(cls, field, **kwargs): - if POSTGRES_AVAILABLE: - if isinstance(field, (JSONField, HStoreField)): - return cls(**kwargs) + def from_field(cls, field, **kwargs) -> Self | None: + if isinstance(field, (JSONField, HStoreField)): + return cls(**kwargs) diff --git a/django_tables2/columns/linkcolumn.py b/django_tables2/columns/linkcolumn.py index adf58762..df288bd5 100644 --- a/django_tables2/columns/linkcolumn.py +++ b/django_tables2/columns/linkcolumn.py @@ -143,37 +143,3 @@ def __init__( ), **extra ) - - -@library.register -class RelatedLinkColumn(LinkColumn): - """ - Render a link to a related object using related object's ``get_absolute_url``, - same parameters as ``~.LinkColumn``. - - .. note :: - - This column should not be used anymore, the `linkify` keyword argument to - regular columns can be used achieve the same results. - - If the related object does not have a method called ``get_absolute_url``, - or if it is not callable, the link will be rendered as '#'. - - Traversing relations is also supported, suppose a Person has a foreign key to - Country which in turn has a foreign key to Continent:: - - class PersonTable(tables.Table): - name = tables.Column() - country = tables.RelatedLinkColumn() - continent = tables.RelatedLinkColumn(accessor="country.continent") - - will render: - - - in column 'country', link to ``person.country.get_absolute_url()`` with the output of - ``str(person.country)`` as ```` contents. - - in column 'continent', a link to ``person.country.continent.get_absolute_url()`` with - the output of ``str(person.country.continent)`` as ```` contents. - - Alternative contents of ```` can be supplied using the ``text`` keyword argument as - documented for `~.columns.LinkColumn`. - """ diff --git a/docs/pages/api-reference.rst b/docs/pages/api-reference.rst index d87ade8c..e17a6139 100644 --- a/docs/pages/api-reference.rst +++ b/docs/pages/api-reference.rst @@ -323,12 +323,6 @@ Columns .. autoclass:: django_tables2.columns.ManyToManyColumn :members: -`.RelatedLinkColumn` -~~~~~~~~~~~~~~~~~~~~ - -.. autoclass:: django_tables2.columns.RelatedLinkColumn - :members: - `.TemplateColumn` ~~~~~~~~~~~~~~~~~ diff --git a/docs/pages/builtin-columns.rst b/docs/pages/builtin-columns.rst index fabde589..1c74025d 100644 --- a/docs/pages/builtin-columns.rst +++ b/docs/pages/builtin-columns.rst @@ -15,7 +15,6 @@ For common use-cases the following columns are included: - `.JSONColumn` -- renders JSON as an indented string in ``
``
 - `.LinkColumn` -- renders ``
`` tags (compose a Django URL) - `.ManyToManyColumn` -- renders a list objects from a `ManyToManyField` -- `.RelatedLinkColumn` -- renders ```` tags linking related objects - `.TemplateColumn` -- renders template code - `.TimeColumn` -- time formatting - `.URLColumn` -- renders ```` tags (absolute URL) diff --git a/example/app/tables.py b/example/app/tables.py index 01f58686..d138ef22 100644 --- a/example/app/tables.py +++ b/example/app/tables.py @@ -73,7 +73,7 @@ class Meta: class SemanticTable(tables.Table): - country = tables.RelatedLinkColumn() + country = tables.Column(linkify=True) class Meta: model = Person diff --git a/tests/columns/test_linkcolumn.py b/tests/columns/test_linkcolumn.py index 01d3da83..a4acf543 100644 --- a/tests/columns/test_linkcolumn.py +++ b/tests/columns/test_linkcolumn.py @@ -6,7 +6,7 @@ import django_tables2 as tables from django_tables2 import A -from ..app.models import Occupation, Person +from ..app.models import Person from ..utils import attrs, build_request @@ -200,29 +200,6 @@ class Table(tables.Table): with self.assertRaisesMessage(TypeError, message): table.as_html(build_request()) - def test_RelatedLinkColumn(self): - carpenter = Occupation.objects.create(name="Carpenter") - Person.objects.create(first_name="Bob", last_name="Builder", occupation=carpenter) - - class Table(tables.Table): - occupation = tables.RelatedLinkColumn() - occupation_linkify = tables.Column(accessor="occupation", linkify=True) - - table = Table(Person.objects.all()) - - url = reverse("occupation", args=[carpenter.pk]) - self.assertEqual(table.rows[0].cells["occupation"], f'Carpenter') - - def test_RelatedLinkColumn_without_model(self): - class Table(tables.Table): - occupation = tables.RelatedLinkColumn() - - table = Table([{"occupation": "Fabricator"}]) - - message = "for linkify=True, 'Fabricator' must have a method get_absolute_url" - with self.assertRaisesMessage(TypeError, message): - table.rows[0].cells["occupation"] - def test_value_returns_a_raw_value_without_html(self): class Table(tables.Table): col = tables.LinkColumn("occupation", args=(A("id"),)) diff --git a/tests/test_extra_columns.py b/tests/test_extra_columns.py index 015c285d..5257b0c9 100644 --- a/tests/test_extra_columns.py +++ b/tests/test_extra_columns.py @@ -181,7 +181,7 @@ def __init__(self, data, *args, **kwargs): if add_occupation_column: kwargs["extra_columns"].append( - ("occupation", tables.RelatedLinkColumn(orderable=False)) + ("occupation", tables.Column(linkify=True, orderable=False)) ) super().__init__(data, *args, **kwargs)