Skip to content

Commit 8fec3ec

Browse files
committed
* Bugfix for Django 1.10 template handling
* Updated to tri.form 4.7.1 * Moved bulk button inside the table tag * Dropped support for Django 1.7
1 parent 728224b commit 8fec3ec

File tree

8 files changed

+50
-60
lines changed

8 files changed

+50
-60
lines changed

HISTORY.rst

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,18 @@
11
Changelog
22
---------
33

4+
4.3.0 (2017-04-25)
5+
~~~~~~~~~~~~~~~~~~
6+
7+
* Bugfix for Django 1.10 template handling
8+
9+
* Updated to tri.form 4.7.1
10+
11+
* Moved bulk button inside the table tag
12+
13+
* Dropped support for Django 1.7
14+
15+
416
4.2.0 (2017-04-21)
517
~~~~~~~~~~~~~~~~~~
618

lib/tri/table/__init__.py

Lines changed: 18 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,6 @@
33
from __future__ import unicode_literals
44

55
import copy
6-
import json
7-
import warnings
86
from collections import OrderedDict
97
from itertools import groupby
108

@@ -13,18 +11,17 @@
1311
from django.conf import settings
1412
from django.core.paginator import Paginator, InvalidPage
1513
from django.http import HttpResponse, Http404, HttpResponseRedirect
16-
from django.template import RequestContext
1714
from django.template.defaultfilters import slugify
18-
from django.template.loader import render_to_string, get_template
15+
from django.template.loader import render_to_string
1916
from django.utils.encoding import force_text, python_2_unicode_compatible
2017
from django.utils.html import conditional_escape, format_html
2118
from django.utils.safestring import mark_safe
2219
from django.db.models import QuerySet
2320
import six
2421
from tri.declarative import declarative, creation_ordered, with_meta, setdefaults, evaluate_recursive, evaluate, getattr_path, sort_after, LAST, setdefaults_path, dispatch, EMPTY, flatten, Namespace, setattr_path
25-
from tri.form import Field, Form, member_from_model, expand_member, create_members_from_model
22+
from tri.form import Field, Form, member_from_model, expand_member, create_members_from_model, render_template, handle_dispatch, DISPATCH_PATH_SEPARATOR
2623
from tri.named_struct import NamedStructField, NamedStruct
27-
from tri.struct import Struct
24+
from tri.struct import Struct, merged
2825
from tri.query import Query, Variable, QueryException, Q_OP_BY_OP
2926

3027
from tri.table.db_compat import setup_db_compat
@@ -542,12 +539,8 @@ def __init__(self, table, row, row_index, template, attrs, extra):
542539

543540
def render(self):
544541
if self.template:
545-
context = RequestContext(self.table.request, dict(bound_row=self, row=self.row, table=self.table))
546-
if isinstance(self.template, six.string_types):
547-
# positional arguments here to get compatibility with both django 1.7 and 1.8+
548-
return render_to_string(self.template, context)
549-
else:
550-
return self.template.render(context)
542+
context = dict(bound_row=self, row=self.row, table=self.table)
543+
return render_template(self.table.request, self.template, context)
551544

552545
return format_html('<tr{}>{}</tr>', self.render_attrs(), self.render_cells())
553546

@@ -607,11 +600,8 @@ def url_title(self):
607600
def render(self):
608601
cell__template = self.bound_column.cell.template
609602
if cell__template:
610-
context = RequestContext(self.table.request, dict(table=self.table, bound_column=self.bound_column, bound_row=self.bound_row, row=self.row, value=self.value, bound_cell=self))
611-
if isinstance(cell__template, six.string_types):
612-
return render_to_string(cell__template, context)
613-
else:
614-
return cell__template.render(context)
603+
context = dict(table=self.table, bound_column=self.bound_column, bound_row=self.bound_row, row=self.row, value=self.value, bound_cell=self)
604+
return render_template(self.table.request, cell__template, context)
615605

616606
return format_html('<td{}>{}</td>', self.render_attrs(), self.render_cell_contents())
617607

@@ -702,7 +692,6 @@ def __init__(self, data=None, request=None, columns=None, columns_dict=None, mod
702692
"""
703693

704694
if data is None: # pragma: no cover
705-
warnings.warn('deriving model from data queryset is deprecated, use Table.from_model', DeprecationWarning)
706695
assert model is not None
707696
data = model.objects.all()
708697

@@ -764,18 +753,15 @@ def generate_columns():
764753
""" :type: tri.declarative.Namespace """
765754

766755
def render_links(self):
767-
return self.render_template_config(self.links, self.context)
756+
return render_template(self.request, self.links.template, self.context)
768757

769758
def render_header(self):
770-
return self.render_template_config(self.header, self.context)
759+
return render_template(self.request, self.header.template, self.context)
771760

772761
def render_filter(self):
773762
if not self.query_form:
774763
return ''
775-
context = self.context
776-
with context.push():
777-
context['form'] = self.query_form
778-
return self.render_template_config(self.filter, context)
764+
return render_template(self.request, self.filter.template, merged(self.context, form=self.query_form))
779765

780766
@staticmethod
781767
def render_template_config(template_config, context):
@@ -942,7 +928,7 @@ def generate_variables():
942928
self.query = Query(
943929
request=request,
944930
variables=variables,
945-
endpoint_dispatch_prefix='__'.join(part for part in [self.endpoint_dispatch_prefix, 'query'] if part is not None),
931+
endpoint_dispatch_prefix=DISPATCH_PATH_SEPARATOR.join(part for part in [self.endpoint_dispatch_prefix, 'query'] if part is not None),
946932
**flatten(self.query_args)
947933
)
948934
self.query_form = self.query.form() if self.query.variables else None
@@ -978,7 +964,7 @@ def generate_bulk_fields():
978964
self.bulk_form = Form(
979965
data=request.POST,
980966
fields=bulk_fields,
981-
endpoint_dispatch_prefix='__'.join(part for part in [self.endpoint_dispatch_prefix, 'bulk'] if part is not None),
967+
endpoint_dispatch_prefix=DISPATCH_PATH_SEPARATOR.join(part for part in [self.endpoint_dispatch_prefix, 'bulk'] if part is not None),
982968
**flatten(self.bulk)
983969
) if bulk_fields else None
984970

@@ -1039,7 +1025,7 @@ class Foo(Model):
10391025
return Table(data=data, model=model, instance=instance, columns=columns, **kwargs)
10401026

10411027
def endpoint_dispatch(self, key, value):
1042-
parts = key.split('__', 1)
1028+
parts = key.split(DISPATCH_PATH_SEPARATOR, 1)
10431029
prefix = parts.pop(0)
10441030
remaining_key = parts[0] if parts else None
10451031
for endpoint, handler in self.endpoint.items():
@@ -1068,7 +1054,6 @@ def table_context(request,
10681054
paginate_by=None,
10691055
page=None,
10701056
extra_context=None,
1071-
context_processors=None,
10721057
paginator=None,
10731058
show_hits=False,
10741059
hit_label='Items'):
@@ -1141,7 +1126,7 @@ def table_context(request,
11411126
'is_paginated': False})
11421127

11431128
base_context.update(extra_context)
1144-
return RequestContext(request, base_context, context_processors)
1129+
return base_context
11451130

11461131

11471132
def set_row_span(rowspan_by_row):
@@ -1164,7 +1149,6 @@ def render_table(request,
11641149
blank_on_empty=False,
11651150
paginate_by=40, # pragma: no mutate
11661151
page=None,
1167-
context_processors=None,
11681152
paginator=None,
11691153
show_hits=False,
11701154
hit_label='Items',
@@ -1191,19 +1175,9 @@ def render_table(request,
11911175
table.prepare(request)
11921176
assert isinstance(table, Table)
11931177

1194-
for key, value in request.GET.items():
1195-
if key.startswith('__'):
1196-
remaining_key = key[2:]
1197-
expected_prefix = table.endpoint_dispatch_prefix
1198-
if expected_prefix is not None:
1199-
parts = remaining_key.split('__', 1)
1200-
prefix = parts.pop(0)
1201-
if prefix != expected_prefix:
1202-
return
1203-
remaining_key = parts[0] if parts else None
1204-
data = table.endpoint_dispatch(key=remaining_key, value=value)
1205-
if data is not None:
1206-
return HttpResponse(json.dumps(data), content_type='application/json')
1178+
should_return, dispatch_result = handle_dispatch(request=request, obj=table)
1179+
if should_return:
1180+
return dispatch_result
12071181

12081182
context['bulk_form'] = table.bulk_form
12091183
context['query_form'] = table.query_form
@@ -1235,7 +1209,6 @@ def render_table(request,
12351209
paginate_by=paginate_by,
12361210
page=page,
12371211
extra_context=context,
1238-
context_processors=context_processors,
12391212
paginator=paginator,
12401213
show_hits=show_hits,
12411214
hit_label=hit_label,
@@ -1251,10 +1224,7 @@ def render_table(request,
12511224
if not template:
12521225
template = template_name
12531226

1254-
if isinstance(template, six.string_types):
1255-
return get_template(template).render(table.context)
1256-
else:
1257-
return template.render(table.context)
1227+
return render_template(request, template, table.context)
12581228

12591229

12601230
def render_table_to_response(*args, **kwargs):

lib/tri/table/templates/tri_table/table_container.html

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,15 @@
55
{% include "tri_table/table.html" %}
66

77
{% if bulk_form %}
8-
<table class="newforms">
8+
<table {{ bulk_form.render_attrs }}>
99
{{ bulk_form }}
10-
</table>
1110

12-
<input type="submit" class="button" value="Bulk change"/>
11+
<tr>
12+
<td colspan="99">
13+
<input type="submit" class="button" value="Bulk change"/>
14+
</td>
15+
</tr>
16+
</table>
1317
{% endif %}
1418

1519
{{ table.render_links }}

requirements.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
tri.declarative >=0.28.0
22
tri.named_struct
3-
tri.form >=4.0.0, <5.0.0
3+
tri.form >=4.7.1, <5.0.0
44
tri.struct
55
tri.query >=3.1.0, <4.0.0
66
six

setup.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@ def run(self):
7878
packages=find_packages('lib'),
7979
package_dir={'': 'lib'},
8080
include_package_data=True,
81-
install_requires=['Django >= 1.7'] + read_reqs('requirements.txt'),
81+
install_requires=['Django >= 1.8'] + read_reqs('requirements.txt'),
8282
license="BSD",
8383
zip_safe=False,
8484
keywords='tri.table',

tests/helpers.py

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,11 @@ def reindent_line(line):
1616
return "\n".join(reindent_line(line) for line in s.splitlines())
1717

1818

19+
def remove_csrf(html_code):
20+
csrf_regex = r'<input[^>]+csrfmiddlewaretoken[^>]+>'
21+
return re.sub(csrf_regex, '', html_code)
22+
23+
1924
def verify_table_html(expected_html, query=None, find=None, links=None, **kwargs):
2025
"""
2126
Verify that the table renders to the expected markup, modulo formatting
@@ -27,10 +32,9 @@ def verify_table_html(expected_html, query=None, find=None, links=None, **kwargs
2732

2833
request = RequestFactory().get("/", query)
2934
request.user = AnonymousUser()
30-
request.META['CSRF_COOKIE'] = None
31-
actual_html = render_table(request=request, links=links, **kwargs)
35+
actual_html = remove_csrf(render_table(request=request, links=links, **kwargs))
3236

33-
prettified_expected = reindent(BeautifulSoup(expected_html).find(**find).prettify()).strip()
34-
prettified_actual = reindent(BeautifulSoup(actual_html).find(**find).prettify()).strip()
37+
prettified_expected = reindent(BeautifulSoup(expected_html, 'html.parser').find(**find).prettify()).strip()
38+
prettified_actual = reindent(BeautifulSoup(actual_html, 'html.parser').find(**find).prettify()).strip()
3539

3640
assert prettified_expected == prettified_actual, "{}\n !=\n {}".format(prettified_expected, prettified_actual)

tests/models.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
from __future__ import unicode_literals
22

33
from django.db import models
4+
from django.db.models import CASCADE
45
from django.utils.encoding import python_2_unicode_compatible
56

67

@@ -14,5 +15,5 @@ def __str__(self):
1415

1516

1617
class Bar(models.Model):
17-
foo = models.ForeignKey(Foo)
18+
foo = models.ForeignKey(Foo, on_delete=CASCADE)
1819
c = models.BooleanField()

tox.ini

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,9 @@
11
[tox]
2-
envlist = py27-django{17,18,19,110},pypy-django{17,18,19,110},py36-django18
2+
envlist = py27-django{18,19,110},pypy-django{18,19,110},py36-django18
33

44
[testenv]
55
commands = {envpython} -m pytest {posargs}
66
deps =
7-
django17: Django >= 1.7, <1.8
87
django18: Django >= 1.8, <1.9
98
django19: Django >= 1.9, <1.10
109
django110: Django >= 1.10, <1.11

0 commit comments

Comments
 (0)