summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRyan Rubin <ryanmrubin@gmail.com>2018-05-25 10:11:46 -0500
committerTim Graham <timograham@gmail.com>2018-05-25 11:22:06 -0400
commitc2a1af883e18b93a77080650feb9e959536d51ca (patch)
treed9b9b17d9fa2c6fafa8a6cf4abf3f08d19fddf86
parent4477d032ac12efc1a9309500aceac263bb104619 (diff)
[2.0.x] Fixed #29400 -- Fixed crash in custom template filters that use decorated functions.
Regression in 620e9dd31a2146d70de740f96a8cb9a6db054fc7. Backport of a8d12bc28069d56e0306770ab9c73738293663f7 from master
-rw-r--r--AUTHORS1
-rw-r--r--django/template/base.py4
-rw-r--r--docs/releases/2.0.6.txt3
-rw-r--r--tests/template_tests/templatetags/custom.py8
-rw-r--r--tests/template_tests/test_custom.py5
5 files changed, 18 insertions, 3 deletions
diff --git a/AUTHORS b/AUTHORS
index 2ee9adecd2..5da3a13745 100644
--- a/AUTHORS
+++ b/AUTHORS
@@ -708,6 +708,7 @@ answer newbie questions, and generally made Django that much better:
ryankanno
Ryan Kelly <ryan@rfk.id.au>
Ryan Niemeyer <https://profiles.google.com/ryan.niemeyer/about>
+ Ryan Rubin <ryanmrubin@gmail.com>
Ryno Mathee <rmathee@gmail.com>
Sam Newman <http://www.magpiebrain.com/>
Sander Dijkhuis <sander.dijkhuis@gmail.com>
diff --git a/django/template/base.py b/django/template/base.py
index 6572eae8ab..a90f8bfdd9 100644
--- a/django/template/base.py
+++ b/django/template/base.py
@@ -51,7 +51,7 @@ times with multiple contexts)
import logging
import re
-from inspect import getcallargs, getfullargspec
+from inspect import getcallargs, getfullargspec, unwrap
from django.template.context import ( # NOQA: imported for backwards compatibility
BaseContext, Context, ContextPopException, RequestContext,
@@ -712,7 +712,7 @@ class FilterExpression:
# First argument, filter input, is implied.
plen = len(provided) + 1
# Check to see if a decorator is providing the real function.
- func = getattr(func, '_decorated_function', func)
+ func = unwrap(func)
args, _, _, defaults, _, _, _ = getfullargspec(func)
alen = len(args)
diff --git a/docs/releases/2.0.6.txt b/docs/releases/2.0.6.txt
index 659c3533e7..5d401a7ea9 100644
--- a/docs/releases/2.0.6.txt
+++ b/docs/releases/2.0.6.txt
@@ -9,4 +9,5 @@ Django 2.0.6 fixes several bugs in 2.0.5.
Bugfixes
========
-* ...
+* Fixed a regression that broke custom template filters that use decorators
+ (:ticket:`29400`).
diff --git a/tests/template_tests/templatetags/custom.py b/tests/template_tests/templatetags/custom.py
index 2e2ccf3782..45acd9655e 100644
--- a/tests/template_tests/templatetags/custom.py
+++ b/tests/template_tests/templatetags/custom.py
@@ -3,6 +3,7 @@ import operator
from django import template
from django.template.defaultfilters import stringfilter
from django.utils.html import escape, format_html
+from django.utils.safestring import mark_safe
register = template.Library()
@@ -14,6 +15,13 @@ def trim(value, num):
@register.filter
+@mark_safe
+def make_data_div(value):
+ """A filter that uses a decorator (@mark_safe)."""
+ return '<div data-name="%s"></div>' % value
+
+
+@register.filter
def noop(value, param=None):
"""A noop filter that always return its first argument and does nothing with
its second (optional) one.
diff --git a/tests/template_tests/test_custom.py b/tests/template_tests/test_custom.py
index b37b5f8f1e..dbc5bc267d 100644
--- a/tests/template_tests/test_custom.py
+++ b/tests/template_tests/test_custom.py
@@ -25,6 +25,11 @@ class CustomFilterTests(SimpleTestCase):
"abcde"
)
+ def test_decorated_filter(self):
+ engine = Engine(libraries=LIBRARIES)
+ t = engine.from_string('{% load custom %}{{ name|make_data_div }}')
+ self.assertEqual(t.render(Context({'name': 'foo'})), '<div data-name="foo"></div>')
+
class TagTestCase(SimpleTestCase):