[Python-modules-commits] [django-tables] 01/08: Import django-tables_1.1.6.orig.tar.gz
Brian May
bam at moszumanska.debian.org
Wed Apr 6 03:14:59 UTC 2016
This is an automated email from the git hooks/post-receive script.
bam pushed a commit to branch master
in repository django-tables.
commit 5119d5474f79dc86c40d7d395e374fc939b68332
Author: Brian May <bam at debian.org>
Date: Wed Apr 6 12:53:12 2016 +1000
Import django-tables_1.1.6.orig.tar.gz
---
.travis.yml | 12 +-
CHANGELOG.md | 29 +++
README.md | 68 -----
README.rst | 106 ++++++++
django_tables2/__init__.py | 10 +-
django_tables2/columns/__init__.py | 2 +-
django_tables2/columns/base.py | 100 ++-----
django_tables2/columns/booleancolumn.py | 40 ++-
django_tables2/columns/checkboxcolumn.py | 55 ++--
django_tables2/columns/datecolumn.py | 4 +-
django_tables2/columns/datetimecolumn.py | 9 +-
django_tables2/columns/emailcolumn.py | 4 +-
django_tables2/columns/filecolumn.py | 27 +-
django_tables2/columns/linkcolumn.py | 80 +++---
django_tables2/columns/templatecolumn.py | 22 +-
django_tables2/rows.py | 14 +-
django_tables2/static/django_tables2/bootstrap.css | 8 +
django_tables2/tables.py | 85 +++---
.../templates/django_tables2/bootstrap.html | 74 ++++++
django_tables2/templates/django_tables2/table.html | 39 ++-
django_tables2/templatetags/django_tables2.py | 112 ++------
django_tables2/utils.py | 128 ++-------
django_tables2/views.py | 16 +-
docs/conf.py | 4 +-
docs/pages/builtin-columns.rst | 2 +-
docs/pages/generic-mixins.rst | 3 +-
docs/pages/localization-control.rst | 4 +-
docs/pages/tutorial.rst | 15 +-
example/app/migrations/0002_person_country.py | 21 ++
example/app/models.py | 6 +
example/app/tables.py | 12 +-
example/app/views.py | 27 +-
example/settings.py | 57 ++--
example/templates/bootstrap_template.html | 22 ++
example/templates/class_based.html | 8 +-
example/urls.py | 4 +-
requirements/common.pip | 3 +-
setup.py | 31 ++-
tests/app/models.py | 41 ++-
tests/app/settings.py | 44 ++--
tests/columns/test_booleancolumn.py | 51 +++-
tests/columns/test_checkboxcolumn.py | 72 ++++--
tests/columns/test_datecolumn.py | 4 +-
tests/columns/test_datetimecolumn.py | 6 +-
tests/columns/test_emailcolumn.py | 1 +
tests/columns/test_filecolumn.py | 59 +++--
tests/columns/test_general.py | 91 ++++---
tests/columns/test_linkcolumn.py | 73 +++---
tests/columns/test_templatecolumn.py | 16 +-
tests/columns/test_timecolumn.py | 39 +++
tests/columns/test_urlcolumn.py | 1 +
tests/test_config.py | 22 +-
tests/test_core.py | 40 +--
tests/test_models.py | 54 +++-
tests/test_rows.py | 5 +
tests/test_templates.py | 286 +++++----------------
tests/test_templatetags.py | 170 ++++++++++++
tests/test_utils.py | 62 +++--
tests/test_views.py | 80 ++++--
tests/utils.py | 60 ++---
tox.ini | 14 +-
61 files changed, 1427 insertions(+), 1127 deletions(-)
diff --git a/.travis.yml b/.travis.yml
index b4527c2..635c462 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -5,16 +5,12 @@ language: python
matrix:
include:
- python: 2.7
- env: TOXENV=py27-1.7
- - python: 2.7
env: TOXENV=py27-1.8
- - python: 3.3
- env: TOXENV=py33-1.7
+ - python: 2.7
+ env: TOXENV=py27-1.9
- python: 3.3
env: TOXENV=py33-1.8
- python: 3.4
- env: TOXENV=py34-1.7
- - python: 3.4
env: TOXENV=py34-1.8
- python: 3.4
env: TOXENV=py34-1.9
@@ -32,5 +28,9 @@ matrix:
- env: TOXENV=py35-master
install:
- pip install tox
+ - pip install python-coveralls
script:
- tox
+
+after_success:
+ coveralls
diff --git a/CHANGELOG.md b/CHANGELOG.md
index a85d6ca..e34e9f9 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,34 @@
# Change log
+## v1.1.5 (2016-04-02)
+- Correct error message about request context processors for current Django (#314)
+
+## v1.1.4 (2016-03-22)
+- Fix broken `setup.py` if Django is not installed before django-tables2 (fixes #312)
+
+## v1.1.3 (2016-03-21)
+- Drop support for Django 1.7
+- Add argument to CheckBoxColumn to render it as checked (original PR: #208)
+
+## v1.1.2 (2016-02-16)
+- Fix `BooleanColumn` with choices set will always render as if `True` (#301)
+- Fix a bug with `TemplateColumn` while using cached template loader (#75)
+
+## v1.1.1 (2016-01-26)
+- Allow Meta.fields to be a list as well as a tuple (#250)
+- Call template.render with a dict in Django >= 1.8. (#298)
+- Added `RelatedLinkColumn()` to render links to related objects (#297)
+- Remove default value from request param to table.as_html()
+
+## v1.1.0 (2016-01-19)
+- Add tests for `TimeColumn`
+- Remove `sortable` argument for `Table` and Column constructors and its associated methods. Deprecated since 2012.
+- Remove deprecated aliases for `attrs` in `CheckboxColumn`.
+- Remove deprecated `OrderByTuple` `cmp` method (deprecated since 2013).
+- Add bootstrap template and (#293, fixes #141, #285)
+- Fix different html for tables with and without pagination (#293, fixes #149, #285)
+- Remove `{% nospaceless %}` template tag and remove wrapping template in `{% spaceless %}` **Possible breaking change**, if you use custom templates.
+
## v1.0.7 (2016-01-03)
- Explicitly check if `column.verbose_name` is not None to support empty column headers (fixes #280)
- Cleanup the example project to make it work with modern Django versions.
diff --git a/README.md b/README.md
deleted file mode 100644
index a69cd6d..0000000
--- a/README.md
+++ /dev/null
@@ -1,68 +0,0 @@
-# django-tables2 - An app for creating HTML tables
-
-[](https://travis-ci.org/bradleyayers/django-tables2)
-
-django-tables2 simplifies the task of turning sets of data into HTML tables. It
-has native support for pagination and sorting. It does for HTML tables what
-`django.forms` does for HTML forms. e.g.
-
-
-
-Its features include:
-
-- Any iterable can be a data-source, but special support for Django querysets is included.
-- The builtin UI does not rely on JavaScript.
-- Support for automatic table generation based on a Django model.
-- Supports custom column functionality via subclassing.
-- Pagination.
-- Column based table sorting.
-- Template tag to enable trivial rendering to HTML.
-- Generic view mixin.
-
-# Example
-
-Creating a table for a model `Simple` is as simple as:
-
-```python
-import django_tables2 as tables
-
-class SimpleTable(tables.Table):
- class Meta:
- model = Simple
-```
-
-This would then be used in a view:
-
-```python
-def simple_list(request):
- queryset = Simple.objects.all()
- table = SimpleTable(queryset)
- return render_to_response("simple_list.html", {"table": table},
- context_instance=RequestContext(request))
-```
-
-And finally in the template:
-
-```
-{% load django_tables2 %}
-{% render_table table %}
-```
-
-This example shows one of the simplest cases, but django-tables2 can do a lot
-more! Check out the [documentation](http://django-tables2.readthedocs.org/en/latest/) for more details.
-
-
-# Building the documentation
-
-If you want to build the docs from within a virtualenv, and Sphinx is installed
-globally, use:
-
- make html SPHINXBUILD="python $(which sphinx-build)"
-
-
-# Publishing a release
-
-1. Bump the version in `django-tables2/__init__.py`.
-2. Update `CHANGELOG.md`.
-3. Create a tag `git tag -a v1.0.6 -m 'tagging v1.0.6'`
-4. Run `python setup.py sdist upload --sign --identity=<your gpg identity>`.
diff --git a/README.rst b/README.rst
new file mode 100644
index 0000000..bec4686
--- /dev/null
+++ b/README.rst
@@ -0,0 +1,106 @@
+django-tables2 - An app for creating HTML tables
+------------------------------------------------
+
+.. image:: https://badge.fury.io/py/django-tables2.svg
+ :target: https://pypi.python.org/pypi/django-tables2
+ :alt: Latest PyPI version
+
+.. image:: https://travis-ci.org/bradleyayers/django-tables2.svg
+ :target: https://travis-ci.org/bradleyayers/django-tables2
+ :alt: Travis CI
+
+django-tables2 simplifies the task of turning sets of data into HTML tables. It
+has native support for pagination and sorting. It does for HTML tables what
+`django.forms` does for HTML forms. e.g.
+
+.. image:: http://dl.dropbox.com/u/33499139/django-tables2/example.png
+ :alt: An example table rendered using django-tables2
+
+Its features include:
+
+- Any iterable can be a data-source, but special support for Django querysets is included.
+- The builtin UI does not rely on JavaScript.
+- Support for automatic table generation based on a Django model.
+- Supports custom column functionality via subclassing.
+- Pagination.
+- Column based table sorting.
+- Template tag to enable trivial rendering to HTML.
+- Generic view mixin.
+
+- `Available on pypi <https://pypi.python.org/pypi/django-tables2>`_
+- `Tested with python 2.7, 3.3, 3.4, 3.5 and Django 1.8, 1.9 <https://travis-ci.org/bradleyayers/django-tables2>`_
+- `Documentation on readthedocs.org <http://django-tables2.readthedocs.org/en/latest/>`_
+
+Example
+-------
+
+Start by adding "django_tables2" to your INSTALLED_APPS setting like this:
+
+.. code:: python
+
+ INSTALLED_APPS = (
+ ...,
+ 'django_tables2',
+ )
+
+Creating a table for a model `Simple` is as simple as:
+
+.. code:: python
+
+ import django_tables2 as tables
+
+ class SimpleTable(tables.Table):
+ class Meta:
+ model = Simple
+
+This would then be used in a view:
+
+.. code:: python
+
+ def simple_list(request):
+ queryset = Simple.objects.all()
+ table = SimpleTable(queryset)
+ return render(request, 'simple_list.html', {'table': table})
+
+And finally in the template:
+
+.. code::
+
+ {% load django_tables2 %}
+ {% render_table table %}
+
+This example shows one of the simplest cases, but django-tables2 can do a lot
+more! Check out the _documentation: http://django-tables2.readthedocs.org/en/latest/ for more details.
+
+Running the tests
+-----------------
+
+With ``tox`` installed, you can run the test suite by typing ``tox``. It will take
+care of installing the correct dependencies. During development, you might not
+want to wait for the tests to run in all environments. In that case, use the ``-e``
+argument to specify an environment:
+
+``tox -e py27-1.9`` to run the tests in python 2.7 with Django 1.9.
+
+To generate a html coverage report:
+
+ PYTHONPATH=. py.test -s --cov=django_tables2 --cov-report html
+
+
+Building the documentation
+--------------------------
+
+If you want to build the docs from within a virtualenv, and Sphinx is installed
+globally, use:
+
+ cd docs/
+ make html SPHINXBUILD="python $(which sphinx-build)"
+
+
+Publishing a release
+--------------------
+
+1. Bump the version in ``django-tables2/__init__.py``.
+2. Update ``CHANGELOG.md``.
+3. Create a tag ``git tag -a v1.0.6 -m 'tagging v1.0.6'``
+4. Run ``python setup.py sdist upload --sign --identity=<your gpg identity>``.
diff --git a/django_tables2/__init__.py b/django_tables2/__init__.py
index abebffd..bd7b4f5 100644
--- a/django_tables2/__init__.py
+++ b/django_tables2/__init__.py
@@ -1,15 +1,11 @@
# coding: utf-8
-# pylint: disable=W0611
from .tables import Table
from .columns import (BooleanColumn, Column, CheckBoxColumn, DateColumn,
DateTimeColumn, EmailColumn, FileColumn, LinkColumn,
- TemplateColumn, URLColumn, TimeColumn)
+ RelatedLinkColumn, TemplateColumn, TimeColumn, URLColumn)
from .config import RequestConfig
from .utils import A
-try:
- from .views import SingleTableMixin, SingleTableView
-except ImportError:
- pass
+from .views import SingleTableMixin, SingleTableView
-__version__ = "1.0.7"
+__version__ = "1.1.6"
diff --git a/django_tables2/columns/__init__.py b/django_tables2/columns/__init__.py
index 756ee01..4abd7a5 100644
--- a/django_tables2/columns/__init__.py
+++ b/django_tables2/columns/__init__.py
@@ -5,7 +5,7 @@ from .datecolumn import DateColumn
from .datetimecolumn import DateTimeColumn
from .emailcolumn import EmailColumn
from .filecolumn import FileColumn
-from .linkcolumn import LinkColumn
+from .linkcolumn import LinkColumn, RelatedLinkColumn
from .templatecolumn import TemplateColumn
from .urlcolumn import URLColumn
from .timecolumn import TimeColumn
diff --git a/django_tables2/columns/base.py b/django_tables2/columns/base.py
index 4d110c6..eaed533 100644
--- a/django_tables2/columns/base.py
+++ b/django_tables2/columns/base.py
@@ -1,17 +1,13 @@
# coding: utf-8
from __future__ import absolute_import, unicode_literals
-import warnings
from collections import OrderedDict
from itertools import islice
-import six
-from django import VERSION as django_version
-from django.db.models.fields import FieldDoesNotExist
-from django_tables2.templatetags.django_tables2 import title
-from django_tables2.utils import A, AttributeDict, OrderBy, OrderByTuple
+from django.utils import six
-from ..utils import python_2_unicode_compatible
+from django_tables2.templatetags.django_tables2 import title
+from django_tables2.utils import Accessor, AttributeDict, OrderBy, OrderByTuple
class Library(object):
@@ -51,7 +47,7 @@ library = Library()
@library.register
-class Column(object): # pylint: disable=R0902
+class Column(object):
"""
Represents a single column of a table.
@@ -147,23 +143,17 @@ class Column(object): # pylint: disable=R0902
def __init__(self, verbose_name=None, accessor=None, default=None,
visible=True, orderable=None, attrs=None, order_by=None,
- sortable=None, empty_values=None, localize=None):
+ empty_values=None, localize=None):
if not (accessor is None or isinstance(accessor, six.string_types) or
callable(accessor)):
raise TypeError('accessor must be a string or callable, not %s' %
type(accessor).__name__)
if callable(accessor) and default is not None:
raise TypeError('accessor must be string when default is used, not callable')
- self.accessor = A(accessor) if accessor else None
+ self.accessor = Accessor(accessor) if accessor else None
self._default = default
self.verbose_name = verbose_name
self.visible = visible
- if sortable is not None:
- warnings.warn('`sortable` is deprecated, use `orderable` instead.',
- DeprecationWarning)
- # if orderable hasn't been specified, we'll use sortable's value
- if orderable is None:
- orderable = sortable
self.orderable = orderable
self.attrs = attrs or {}
# massage order_by into an OrderByTuple or None
@@ -218,15 +208,6 @@ class Column(object): # pylint: disable=R0902
"""
return value
- @property
- def sortable(self):
- """
- *deprecated* -- use `.orderable` instead.
- """
- warnings.warn('`sortable` is deprecated, use `orderable` instead.',
- DeprecationWarning)
- return self.orderable
-
@classmethod
def from_field(cls, field):
"""
@@ -245,14 +226,14 @@ class Column(object): # pylint: disable=R0902
# Since this method is inherited by every subclass, only provide a
# column if this class was asked directly.
if cls is Column:
- if hasattr(field, "get_related_field"):
+ if hasattr(field, 'get_related_field'):
verbose_name = field.get_related_field().verbose_name
else:
verbose_name = getattr(field, 'verbose_name', field.name)
return cls(verbose_name=verbose_name)
- at python_2_unicode_compatible
+ at six.python_2_unicode_compatible
class BoundColumn(object):
"""
A *run-time* version of `.Column`. The difference between
@@ -291,7 +272,7 @@ class BoundColumn(object):
Returns the string used to access data for this column out of the data
source.
"""
- return self.column.accessor or A(self.name)
+ return self.column.accessor or Accessor(self.name)
@property
def attrs(self):
@@ -307,24 +288,25 @@ class BoundColumn(object):
# Find the relevant th attributes (fall back to cell if th isn't
# explicitly specified).
- attrs["td"] = td = AttributeDict(attrs.get('td', attrs.get('cell', {})))
- attrs["th"] = th = AttributeDict(attrs.get("th", attrs.get("cell", {})))
+ attrs['th'] = AttributeDict(attrs.get('th', attrs.get('cell', {})))
+ attrs['td'] = AttributeDict(attrs.get('td', attrs.get('cell', {})))
+
# make set of existing classes.
- th_class = set((c for c in th.get("class", "").split(" ") if c)) # pylint: disable=C0103
- td_class = set((c for c in td.get("class", "").split(" ") if c)) # pylint: disable=C0103
+ th_class = set((c for c in attrs['th'].get('class', '').split(' ') if c))
+ td_class = set((c for c in attrs['td'].get('class', '').split(' ') if c))
+
# add classes for ordering
if self.orderable:
- th_class.add("orderable")
- th_class.add("sortable") # backwards compatible
+ th_class.add('orderable')
if self.is_ordered:
- th_class.add("desc" if self.order_by_alias.is_descending else "asc")
+ th_class.add('desc' if self.order_by_alias.is_descending else 'asc')
+
# Always add the column name as a class
th_class.add(self.name)
td_class.add(self.name)
- if th_class:
- th['class'] = " ".join(sorted(th_class))
- if td_class:
- td['class'] = " ".join(sorted(td_class))
+
+ attrs['th']['class'] = ' '.join(sorted(th_class))
+ attrs['td']['class'] = ' '.join(sorted(td_class))
return attrs
@property
@@ -424,15 +406,6 @@ class BoundColumn(object):
return self.name in (self.table.order_by or ())
@property
- def sortable(self):
- """
- *deprecated* -- use `orderable` instead.
- """
- warnings.warn('`%s.sortable` is deprecated, use `orderable`'
- % type(self).__name__, DeprecationWarning)
- return self.orderable
-
- @property
def orderable(self):
"""
Return a `bool` depending on whether this column supports ordering.
@@ -464,22 +437,7 @@ class BoundColumn(object):
# Try to use a model field's verbose_name
if hasattr(self.table.data, 'queryset') and hasattr(self.table.data.queryset, 'model'):
model = self.table.data.queryset.model
- parts = self.accessor.split('.')
- field = None
- for part in parts:
-
- try:
- if django_version < (1, 8, 0):
- field, _, _, _ = model._meta.get_field_by_name(part)
- else:
- field = model._meta.get_field(part)
-
- except FieldDoesNotExist:
- break
- if hasattr(field, 'rel') and hasattr(field.rel, 'to'):
- model = field.rel.to
- continue
- break
+ field = Accessor(self.accessor).get_field(model)
if field:
if hasattr(field, 'field'):
name = field.field.verbose_name
@@ -566,25 +524,15 @@ class BoundColumns(object):
Same as `BoundColumns.all` but only returns orderable columns.
This is useful in templates, where iterating over the full
- set and checking ``{% if column.sortable %}`` can be problematic in
+ set and checking ``{% if column.ordarable %}`` can be problematic in
conjunction with e.g. ``{{ forloop.last }}`` (the last column might not
be the actual last that is rendered).
"""
return (x for x in self.iterall() if x.orderable)
- def itersortable(self):
- warnings.warn('`itersortable` is deprecated, use `iterorderable` instead.',
- DeprecationWarning)
- return self.iterorderable()
-
def orderable(self):
return list(self.iterorderable())
- def sortable(self):
- warnings.warn("`sortable` is deprecated, use `orderable` instead.",
- DeprecationWarning)
- return self.orderable
-
def itervisible(self):
"""
Same as `.iterorderable` but only returns visible `.BoundColumn`
@@ -645,5 +593,5 @@ class BoundColumns(object):
raise KeyError("Column with name '%s' does not exist; "
"choices are: %s" % (index, self.names()))
else:
- raise TypeError('row indices must be integers or str, not %s'
+ raise TypeError('Column indices must be integers or str, not %s'
% type(index).__name__)
diff --git a/django_tables2/columns/booleancolumn.py b/django_tables2/columns/booleancolumn.py
index 3c9b41e..6a8fc61 100644
--- a/django_tables2/columns/booleancolumn.py
+++ b/django_tables2/columns/booleancolumn.py
@@ -1,11 +1,13 @@
# coding: utf-8
from __future__ import absolute_import, unicode_literals
-from .base import Column, library
+
from django.db import models
-from django.utils.html import escape
-from django.utils.safestring import mark_safe
-from django_tables2.utils import AttributeDict
-import six
+from django.utils import six
+from django.utils.html import escape, format_html
+
+from django_tables2.utils import Accessor, AttributeDict
+
+from .base import Column, library
@library.register
@@ -30,16 +32,32 @@ class BooleanColumn(Column):
self.yesno = (yesno.split(',') if isinstance(yesno, six.string_types)
else tuple(yesno))
if null:
- kwargs["empty_values"] = ()
+ kwargs['empty_values'] = ()
super(BooleanColumn, self).__init__(**kwargs)
- def render(self, value):
+ def render(self, value, record, bound_column):
+ # if record is a model, we need to check if it has choices defined.
+ # If that's the case, we need to inverse lookup the value to convert to
+ # a boolean.
+ if hasattr(record, '_meta'):
+ try:
+ field = bound_column.accessor.get_field(record)
+
+ if hasattr(field, 'choices') and field.choices is not None:
+ value = next(val for val, name in field.choices if name == value)
+ except:
+ pass
+
value = bool(value)
text = self.yesno[int(not value)]
- html = '<span %s>%s</span>'
- attrs = {"class": six.text_type(value).lower()}
- attrs.update(self.attrs.get("span", {}))
- return mark_safe(html % (AttributeDict(attrs).as_html(), escape(text)))
+ attrs = {'class': six.text_type(value).lower()}
+ attrs.update(self.attrs.get('span', {}))
+
+ return format_html(
+ '<span {}>{}</span>',
+ AttributeDict(attrs).as_html(),
+ escape(text)
+ )
@classmethod
def from_field(cls, field):
diff --git a/django_tables2/columns/checkboxcolumn.py b/django_tables2/columns/checkboxcolumn.py
index d2889f6..e5b4ed1 100644
--- a/django_tables2/columns/checkboxcolumn.py
+++ b/django_tables2/columns/checkboxcolumn.py
@@ -1,8 +1,10 @@
# coding: utf-8
from __future__ import absolute_import, unicode_literals
+
from django.utils.safestring import mark_safe
-from django_tables2.utils import AttributeDict
-import warnings
+
+from django_tables2.utils import Accessor, AttributeDict
+
from .base import Column, library
@@ -38,26 +40,13 @@ class CheckBoxColumn(Column):
- *input* -- ``<input>`` elements in both ``<td>`` and ``<th>``.
- *th__input* -- Replaces *input* attrs in header cells.
- *td__input* -- Replaces *input* attrs in body cells.
- """
- def __init__(self, attrs=None, **extra):
- # For backwards compatibility, passing in a normal dict effectively
- # should assign attributes to the `<input>` tag.
- valid = set(("input", "th__input", "td__input", "th", "td", "cell"))
- if attrs and not set(attrs) & set(valid):
- # if none of the keys in attrs are actually valid, assume it's some
- # old code that should be be interpreted as {"td__input": ...}
- warnings.warn('attrs keys must be one of %s, interpreting as {"td__input": %s}'
- % (', '.join(valid), attrs), DeprecationWarning)
- attrs = {"td__input": attrs}
- # This is done for backwards compatible too, there used to be a
- # ``header_attrs`` argument, but this has been deprecated. We'll
- # maintain it for a while by translating it into ``head.checkbox``.
- if "header_attrs" in extra:
- warnings.warn('header_attrs argument is deprecated, '
- 'use attrs={"th__input": ...} instead',
- DeprecationWarning)
- attrs.setdefault('th__input', {}).update(extra.pop('header_attrs'))
+ To render the checkbox as checked, use the *checked* argument with a
+ accessor, boolean or callable returning boolean. If it resolves to a truthy
+ value, the checkbox will be rendered as checked.
+ """
+ def __init__(self, attrs=None, checked=None, **extra):
+ self.checked = checked
kwargs = {'orderable': False, 'attrs': attrs}
kwargs.update(extra)
super(CheckBoxColumn, self).__init__(**kwargs)
@@ -70,13 +59,35 @@ class CheckBoxColumn(Column):
attrs = AttributeDict(default, **(specific or general or {}))
return mark_safe('<input %s/>' % attrs.as_html())
- def render(self, value, bound_column): # pylint: disable=W0221
+ def render(self, value, bound_column, record):
default = {
'type': 'checkbox',
'name': bound_column.name,
'value': value
}
+ if self.is_checked(value, record):
+ default.update({
+ 'checked': 'checked',
+ })
+
general = self.attrs.get('input')
specific = self.attrs.get('td__input')
attrs = AttributeDict(default, **(specific or general or {}))
return mark_safe('<input %s/>' % attrs.as_html())
+
+ def is_checked(self, value, record):
+ """
+ Determine if the checkbox should be checked
+ """
+ if self.checked is None:
+ return False
+ if self.checked is True:
+ return True
+
+ if callable(self.checked):
+ return bool(self.checked(value, record))
+
+ checked = Accessor(self.checked)
+ if checked in record:
+ return bool(record[checked])
+ return False
diff --git a/django_tables2/columns/datecolumn.py b/django_tables2/columns/datecolumn.py
index a2ed466..9598390 100644
--- a/django_tables2/columns/datecolumn.py
+++ b/django_tables2/columns/datecolumn.py
@@ -1,6 +1,8 @@
# coding: utf-8
from __future__ import absolute_import, unicode_literals
+
from django.db import models
+
from .base import library
from .templatecolumn import TemplateColumn
@@ -17,7 +19,7 @@ class DateColumn(TemplateColumn):
``SHORT_DATE_FORMAT`` setting, otherwise use ``DATE_FORMAT``
:type short: `bool`
"""
- def __init__(self, format=None, short=True, *args, **kwargs): # pylint: disable=W0622
+ def __init__(self, format=None, short=True, *args, **kwargs):
if format is None:
format = 'SHORT_DATE_FORMAT' if short else 'DATE_FORMAT'
template = '{{ value|date:"%s"|default:default }}' % format
diff --git a/django_tables2/columns/datetimecolumn.py b/django_tables2/columns/datetimecolumn.py
index 41c51c9..9ee469d 100644
--- a/django_tables2/columns/datetimecolumn.py
+++ b/django_tables2/columns/datetimecolumn.py
@@ -1,6 +1,8 @@
# coding: utf-8
from __future__ import absolute_import, unicode_literals
+
from django.db import models
+
from .base import library
from .templatecolumn import TemplateColumn
@@ -10,13 +12,14 @@ class DateTimeColumn(TemplateColumn):
"""
A column that renders datetimes in the local timezone.
- :param format: format string for datetime (optional)
+ :param format: format string for datetime (optional).
+ Note that *format* uses Django's `date` template tag syntax.
:type format: `unicode`
- :param short: if *format* is not specifid, use Django's
+ :param short: if *format* is not specified, use Django's
``SHORT_DATETIME_FORMAT``, else ``DATETIME_FORMAT``
:type short: `bool`
"""
- def __init__(self, format=None, short=True, *args, **kwargs): # pylint: disable=W0622
+ def __init__(self, format=None, short=True, *args, **kwargs):
if format is None:
format = 'SHORT_DATETIME_FORMAT' if short else 'DATETIME_FORMAT'
template = '{{ value|date:"%s"|default:default }}' % format
diff --git a/django_tables2/columns/emailcolumn.py b/django_tables2/columns/emailcolumn.py
index 5736026..b6804f8 100644
--- a/django_tables2/columns/emailcolumn.py
+++ b/django_tables2/columns/emailcolumn.py
@@ -1,6 +1,8 @@
# coding: utf-8
from __future__ import absolute_import, unicode_literals
+
from django.db import models
+
from .base import library
from .linkcolumn import BaseLinkColumn
@@ -31,7 +33,7 @@ class EmailColumn(BaseLinkColumn):
"""
def render(self, value):
- return self.render_link("mailto:%s" % value, text=value)
+ return self.render_link('mailto:%s' % value, text=value)
@classmethod
def from_field(cls, field):
diff --git a/django_tables2/columns/filecolumn.py b/django_tables2/columns/filecolumn.py
index 6555ec9..6517e7f 100644
--- a/django_tables2/columns/filecolumn.py
+++ b/django_tables2/columns/filecolumn.py
@@ -1,9 +1,14 @@
# coding: utf-8
from __future__ import absolute_import, unicode_literals
+
+import os
+
from django.db import models
+from django.utils.html import format_html
from django.utils.safestring import mark_safe
+
from django_tables2.utils import AttributeDict
-import os
+
from .base import Column, library
@@ -35,7 +40,7 @@ class FileColumn(Column):
super(FileColumn, self).__init__(**kwargs)
def render(self, value):
- storage = getattr(value, "storage", None)
+ storage = getattr(value, 'storage', None)
exists = None
url = None
if storage:
@@ -45,7 +50,7 @@ class FileColumn(Column):
url = storage.url(value.name)
else:
- if self.verify_exists and hasattr(value, "name"):
+ if self.verify_exists and hasattr(value, 'name'):
# ignore negatives, perhaps the file has a name but it doesn't
# represent a local path... better to stay neutral than give a
# false negative.
@@ -57,19 +62,17 @@ class FileColumn(Column):
if url:
attrs['href'] = url
- # add "exists" or "missing" to the class list
classes = [c for c in attrs.get('class', '').split(' ') if c]
- if exists is True:
- classes.append("exists")
- elif exists is False:
- classes.append("missing")
- attrs['class'] = " ".join(classes)
+ if exists is not None:
+ classes.append('exists' if exists else 'missing')
+ attrs['class'] = ' '.join(classes)
- html = '<{tag} {attrs}>{text}</{tag}>'.format(
+ return format_html(
+ '<{tag} {attrs}>{text}</{tag}>',
tag=tag,
attrs=attrs.as_html(),
- text=os.path.basename(value.name))
- return mark_safe(html)
+ text=os.path.basename(value.name)
+ )
@classmethod
def from_field(cls, field):
diff --git a/django_tables2/columns/linkcolumn.py b/django_tables2/columns/linkcolumn.py
index 3b15cdc..2e3488c 100644
--- a/django_tables2/columns/linkcolumn.py
+++ b/django_tables2/columns/linkcolumn.py
@@ -1,11 +1,10 @@
# coding: utf-8
from __future__ import absolute_import, unicode_literals
-import warnings
-
from django.core.urlresolvers import reverse
from django.utils.html import format_html
-from django_tables2.utils import A, AttributeDict
+
+from django_tables2.utils import Accessor, AttributeDict
from .base import Column, library
@@ -18,13 +17,6 @@ class BaseLinkColumn(Column):
``<a href="...">`` tag.
"""
def __init__(self, attrs=None, *args, **kwargs):
- valid = set(("a", "th", "td", "cell"))
- if attrs and not set(attrs) & set(valid):
- # if none of the keys in attrs are actually valid, assume it's some
- # old code that should be be interpreted as {"a": ...}
- warnings.warn('attrs keys must be one of %s, interpreting as {"a": %s}'
- % (', '.join(valid), attrs), DeprecationWarning)
- attrs = {"a": attrs}
kwargs['attrs'] = attrs
super(BaseLinkColumn, self).__init__(*args, **kwargs)
@@ -40,9 +32,11 @@ class BaseLinkColumn(Column):
self.attrs.get('a', {}))
attrs['href'] = uri
- return format_html('<a {attrs}>{text}</a>',
- attrs=attrs.as_html(),
- text=text)
+ return format_html(
+ '<a {attrs}>{text}</a>',
+ attrs=attrs.as_html(),
+ text=text
+ )
@library.register
@@ -127,49 +121,49 @@ class LinkColumn(BaseLinkColumn):
self.current_app = current_app
self.text_value = text
- def compose_url(self, record):
+ def compose_url(self, record, *args, **kwargs):
'''Compose the url if the column is constructed with a viewname.'''
- if isinstance(self.viewname, A):
- viewname = self.viewname.resolve(record)
- else:
- viewname = self.viewname
- # The following params + if statements create optional arguments to
- # pass to Django's reverse() function.
+ if self.viewname is None:
+ if not hasattr(record, 'get_absolute_url'):
+ raise TypeError('if viewname=None, record must define a get_absolute_url')
+ return record.get_absolute_url()
+
+ def resolve_if_accessor(val):
+ return val.resolve(record) if isinstance(val, Accessor) else val
+
+ viewname = resolve_if_accessor(self.viewname)
+
+ # Collect the optional arguments for django's reverse()
params = {}
if self.urlconf:
- params['urlconf'] = (self.urlconf.resolve(record)
- if isinstance(self.urlconf, A)
- else self.urlconf)
+ params['urlconf'] = resolve_if_accessor(self.urlconf)
if self.args:
- params['args'] = [a.resolve(record) if isinstance(a, A) else a
- for a in self.args]
+ params['args'] = [resolve_if_accessor(a) for a in self.args]
if self.kwargs:
- params['kwargs'] = {}
- for key, val in self.kwargs.items():
- # If we're dealing with an Accessor (A), resolve it, otherwise
- # use the value verbatim.
- params['kwargs'][str(key)] = (val.resolve(record)
- if isinstance(val, A) else val)
+ params['kwargs'] = {key: resolve_if_accessor(val) for key, val in self.kwargs.items()}
if self.current_app:
- params['current_app'] = (self.current_app.resolve(record)
- if isinstance(self.current_app, A)
- else self.current_app)
+ params['current_app'] = resolve_if_accessor(self.current_app)
return reverse(viewname, **params)
- def render(self, value, record, bound_column): # pylint: disable=W0221
- if self.viewname is None:
- if not hasattr(record, 'get_absolute_url'):
- raise TypeError('if viewname=None, record must define a get_absolute_url')
- url = record.get_absolute_url()
- else:
- url = self.compose_url(record)
-
+ def render(self, value, record, bound_column):
text_value = value
if self.text_value:
text_value = self.text_value
if callable(text_value):
text_value = text_value(record)
- return self.render_link(url, text=text_value)
+ return self.render_link(self.compose_url(record, bound_column), text=text_value)
+
+
+ at library.register
+class RelatedLinkColumn(LinkColumn):
+ '''
+ Render a link to a related object using related object's ``get_absolute_url``
+ '''
+
+ def compose_url(self, record, bound_column):
+ accessor = self.accessor if self.accessor else Accessor(bound_column)
+
+ return accessor.resolve(record).get_absolute_url()
diff --git a/django_tables2/columns/templatecolumn.py b/django_tables2/columns/templatecolumn.py
index 223e566..4686d2c 100644
--- a/django_tables2/columns/templatecolumn.py
+++ b/django_tables2/columns/templatecolumn.py
@@ -1,7 +1,9 @@
# coding: utf-8
from __future__ import absolute_import, unicode_literals
+
... 3504 lines suppressed ...
--
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/python-modules/packages/django-tables.git
More information about the Python-modules-commits
mailing list