From: Bradley Ayers Date: Thu, 2 Jun 2011 23:04:38 +0000 (+1000) Subject: Fixed issue #8 where a TemplateSyntaxError would be raised when using {% render_table... X-Git-Tag: v0.5.0^2~6 X-Git-Url: http://git.tremily.us/?p=django-tables2.git;a=commitdiff_plain;h=0d88f08942770c69503fcf50e31fcf22b7dc220a Fixed issue #8 where a TemplateSyntaxError would be raised when using {% render_table %} with a non-existant variable. The template tag now returns TEMPLATE_STRING_IF_INVALID when not in debug mode. --- diff --git a/django_tables/templatetags/django_tables.py b/django_tables/templatetags/django_tables.py index b455eae..1166a3d 100644 --- a/django_tables/templatetags/django_tables.py +++ b/django_tables/templatetags/django_tables.py @@ -14,6 +14,7 @@ Examples: import urllib import tokenize import StringIO +from django.conf import settings from django import template from django.template.loader import get_template from django.utils.safestring import mark_safe @@ -89,18 +90,26 @@ class RenderTableNode(template.Node): self.table_var = template.Variable(table_var_name) def render(self, context): - table = self.table_var.resolve(context) - if 'request' not in context: - raise AssertionError('{% render_table %} requires that the ' - 'template context contains the HttpRequest in' - ' a "request" variable, check your ' - ' TEMPLATE_CONTEXT_PROCESSORS setting.') - context = template.Context({'request': context['request'], 'table': table}) try: - table.request = context['request'] - return get_template('django_tables/table.html').render(context) - finally: - del table.request + # may raise VariableDoesNotExist + table = self.table_var.resolve(context) + if "request" not in context: + raise AssertionError("{% render_table %} requires that the " + "template context contains the HttpRequest in" + " a 'request' variable, check your " + " TEMPLATE_CONTEXT_PROCESSORS setting.") + context = template.Context({"request": context["request"], + "table": table}) + try: + table.request = context["request"] + return get_template("django_tables/table.html").render(context) + finally: + del table.request + except: + if settings.DEBUG: + raise + else: + return settings.TEMPLATE_STRING_IF_INVALID @register.tag diff --git a/tests/templates.py b/tests/templates.py index 2a5f482..6831919 100644 --- a/tests/templates.py +++ b/tests/templates.py @@ -1,63 +1,54 @@ # -*- coding: utf8 -*- -"""Test template specific functionality. - -Make sure tables expose their functionality to templates right. This -generally about testing "out"-functionality of the tables, whether -via templates or otherwise. Whether a test belongs here or, say, in -``test_basic``, is not always a clear-cut decision. -""" - -from django.template import Template, Context +from django.template import Template, Context, VariableDoesNotExist from django.http import HttpRequest +from django.conf import settings import django_tables as tables from attest import Tests, Assert from xml.etree import ElementTree as ET + templates = Tests() -@templates.context -def context(): - class Context(object): - class CountryTable(tables.Table): - name = tables.Column() - capital = tables.Column(sortable=False) - 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.') - - 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} - ] - yield Context +class CountryTable(tables.Table): + name = tables.Column() + capital = tables.Column(sortable=False) + 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} +] @templates.test -def as_html(context): - table = context.CountryTable(context.data) - root = ET.fromstring(table.as_html()) +def as_html(): + table = CountryTable(MEMORY_DATA) + root = ET.fromstring(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 = context.CountryTable([]) + table = CountryTable([]) root = ET.fromstring(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 = context.CountryTable([], empty_text='this table is empty') + table = CountryTable([], empty_text='this table is empty') root = ET.fromstring(table.as_html()) Assert(1) == len(root.findall('.//thead/tr')) Assert(4) == len(root.findall('.//thead/tr/th')) @@ -68,9 +59,9 @@ def as_html(context): @templates.test -def custom_rendering(context): +def custom_rendering(): """For good measure, render some actual templates.""" - countries = context.CountryTable(context.data) + countries = CountryTable(MEMORY_DATA) context = Context({'countries': countries}) # automatic and manual column verbose names @@ -89,38 +80,45 @@ def custom_rendering(context): @templates.test -def templatetag(context): +def templatetag(): # ensure it works with a multi-order-by - table = context.CountryTable(context.data, order_by=('name', 'population')) + table = CountryTable(MEMORY_DATA, order_by=('name', 'population')) t = Template('{% load django_tables %}{% render_table table %}') html = t.render(Context({'request': HttpRequest(), 'table': table})) - - root = ET.fromstring(html) + + root = ET.fromstring(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 = context.CountryTable([]) + table = CountryTable([]) t = Template('{% load django_tables %}{% render_table table %}') html = t.render(Context({'request': HttpRequest(), 'table': table})) - root = ET.fromstring(html) + root = ET.fromstring(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 - table = context.CountryTable([], empty_text='this table is empty') + table = CountryTable([], empty_text='this table is empty') t = Template('{% load django_tables %}{% render_table table %}') html = t.render(Context({'request': HttpRequest(), 'table': table})) - root = ET.fromstring(html) + root = ET.fromstring(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) + t = Template('{% load django_tables %}{% render_table this_doesnt_exist %}') + with Assert.raises(VariableDoesNotExist): + settings.DEBUG = True + t.render(Context()) + + # Should be silent with debug off + settings.DEBUG = False + t.render(Context())