# coding: utf-8
from __future__ import unicode_literals
from django.test import TransactionTestCase
import django
from django.core.exceptions import ImproperlyConfigured
from django.template import Template, RequestContext, Context
from django.utils.translation import ugettext_lazy
from django.utils.safestring import mark_safe
from .app.models import Person, Region
import django_tables2 as tables
from django_tables2.config import RequestConfig
from django_tables2.utils import build_request
try:
from urlparse import parse_qs
except ImportError:
from urllib.parse import parse_qs
import lxml.etree
import lxml.html
import six
from .utils import parse, translation
import pytest
class CountryTable(tables.Table):
name = tables.Column()
capital = tables.Column(orderable=False,
verbose_name=ugettext_lazy("Capital"))
population = tables.Column(verbose_name='Population Size')
currency = tables.Column(visible=False)
tld = tables.Column(visible=False, verbose_name='Domain')
calling_code = tables.Column(accessor='cc',
verbose_name='Phone Ext.')
MEMORY_DATA = [
{'name': 'Germany', 'capital': 'Berlin', 'population': 83,
'currency': 'Euro (€)', 'tld': 'de', 'cc': 49},
{'name': 'France', 'population': 64, 'currency': 'Euro (€)',
'tld': 'fr', 'cc': 33},
{'name': 'Netherlands', 'capital': 'Amsterdam', 'cc': '31'},
{'name': 'Austria', 'cc': 43, 'currency': 'Euro (€)',
'population': 8}
]
def test_as_html():
table = CountryTable(MEMORY_DATA)
root = parse(table.as_html())
assert len(root.findall('.//thead/tr')) == 1
assert len(root.findall('.//thead/tr/th')) == 4
assert len(root.findall('.//tbody/tr')) == 4
assert len(root.findall('.//tbody/tr/td')) == 16
# no data with no empty_text
table = CountryTable([])
root = parse(table.as_html())
assert 1 == len(root.findall('.//thead/tr'))
assert 4 == len(root.findall('.//thead/tr/th'))
assert 0 == len(root.findall('.//tbody/tr'))
# no data WITH empty_text
table = CountryTable([], empty_text='this table is empty')
root = parse(table.as_html())
assert 1 == len(root.findall('.//thead/tr'))
assert 4 == len(root.findall('.//thead/tr/th'))
assert 1 == len(root.findall('.//tbody/tr'))
assert 1 == len(root.findall('.//tbody/tr/td'))
assert int(root.find('.//tbody/tr/td').attrib['colspan']) == len(root.findall('.//thead/tr/th'))
assert root.find('.//tbody/tr/td').text == 'this table is empty'
# with custom template
table = CountryTable([], template="django_tables2/table.html")
table.as_html()
def test_custom_rendering():
"""For good measure, render some actual templates."""
countries = CountryTable(MEMORY_DATA)
context = Context({'countries': countries})
# automatic and manual column verbose names
template = Template('{% for column in countries.columns %}{{ column }}/'
'{{ column.name }} {% endfor %}')
result = ('Name/name Capital/capital Population Size/population '
'Phone Ext./calling_code ')
assert result == template.render(context)
# row values
template = Template('{% for row in countries.rows %}{% for value in row %}'
'{{ value }} {% endfor %}{% endfor %}')
result = ('Germany Berlin 83 49 France — 64 33 Netherlands Amsterdam '
'— 31 Austria — 8 43 ')
assert result == template.render(context)
def test_render_table_templatetag(settings):
# ensure it works with a multi-order-by
request = build_request('/')
table = CountryTable(MEMORY_DATA, order_by=('name', 'population'))
RequestConfig(request).configure(table)
template = Template('{% load django_tables2 %}{% render_table table %}')
html = template.render(Context({'request': request, 'table': table}))
root = parse(html)
assert len(root.findall('.//thead/tr')) == 1
assert len(root.findall('.//thead/tr/th')) == 4
assert len(root.findall('.//tbody/tr')) == 4
assert len(root.findall('.//tbody/tr/td')) == 16
assert root.find('ul[@class="pagination"]/li[@class="cardinality"]').text == '4 items'
# no data with no empty_text
table = CountryTable([])
template = Template('{% load django_tables2 %}{% render_table table %}')
html = template.render(Context({'request': build_request('/'), 'table': table}))
root = parse(html)
assert len(root.findall('.//thead/tr')) == 1
assert len(root.findall('.//thead/tr/th')) == 4
assert len(root.findall('.//tbody/tr')) == 0
# no data WITH empty_text
request = build_request('/')
table = CountryTable([], empty_text='this table is empty')
RequestConfig(request).configure(table)
template = Template('{% load django_tables2 %}{% render_table table %}')
html = template.render(Context({'request': request, 'table': table}))
root = parse(html)
assert len(root.findall('.//thead/tr')) == 1
assert len(root.findall('.//thead/tr/th')) == 4
assert len(root.findall('.//tbody/tr')) == 1
assert len(root.findall('.//tbody/tr/td')) == 1
assert int(root.find('.//tbody/tr/td').attrib['colspan']) == len(root.findall('.//thead/tr/th'))
assert root.find('.//tbody/tr/td').text == 'this table is empty'
# variable that doesn't exist (issue #8)
template = Template('{% load django_tables2 %}'
'{% render_table this_doesnt_exist %}')
with pytest.raises(ValueError):
settings.DEBUG = True
template.render(Context())
# Should still be noisy with debug off
with pytest.raises(ValueError):
settings.DEBUG = False
template.render(Context())
def test_render_table_should_support_template_argument():
table = CountryTable(MEMORY_DATA, order_by=('name', 'population'))
template = Template('{% load django_tables2 %}'
'{% render_table table "dummy.html" %}')
request = build_request('/')
context = RequestContext(request, {'table': table})
assert template.render(context) == 'dummy template contents\n'
@pytest.mark.django_db
def test_render_table_supports_queryset():
for name in ("Mackay", "Brisbane", "Maryborough"):
Region.objects.create(name=name)
template = Template('{% load django_tables2 %}{% render_table qs %}')
html = template.render(Context({'qs': Region.objects.all(),
'request': build_request('/')}))
root = parse(html)
assert [e.text for e in root.findall('.//thead/tr/th/a')] == ["ID", "name", "mayor"]
td = [[td.text for td in tr.findall('td')] for tr in root.findall('.//tbody/tr')]
db = []
for region in Region.objects.all():
db.append([six.text_type(region.id), region.name, "—"])
assert td == db
def test_querystring_templatetag():
template = Template('{% load django_tables2 %}'
'{% querystring "name"="Brad" foo.bar=value %}')
# Should be something like: