[2.0.x] Fixed #29400 -- Fixed crash in custom template filters that use decorated functions.

Regression in 620e9dd31a.

Backport of a8d12bc280 from master
This commit is contained in:
Ryan Rubin 2018-05-25 10:11:46 -05:00 committed by Tim Graham
parent 4477d032ac
commit c2a1af883e
5 changed files with 18 additions and 3 deletions

View File

@ -708,6 +708,7 @@ answer newbie questions, and generally made Django that much better:
ryankanno ryankanno
Ryan Kelly <ryan@rfk.id.au> Ryan Kelly <ryan@rfk.id.au>
Ryan Niemeyer <https://profiles.google.com/ryan.niemeyer/about> Ryan Niemeyer <https://profiles.google.com/ryan.niemeyer/about>
Ryan Rubin <ryanmrubin@gmail.com>
Ryno Mathee <rmathee@gmail.com> Ryno Mathee <rmathee@gmail.com>
Sam Newman <http://www.magpiebrain.com/> Sam Newman <http://www.magpiebrain.com/>
Sander Dijkhuis <sander.dijkhuis@gmail.com> Sander Dijkhuis <sander.dijkhuis@gmail.com>

View File

@ -51,7 +51,7 @@ times with multiple contexts)
import logging import logging
import re import re
from inspect import getcallargs, getfullargspec from inspect import getcallargs, getfullargspec, unwrap
from django.template.context import ( # NOQA: imported for backwards compatibility from django.template.context import ( # NOQA: imported for backwards compatibility
BaseContext, Context, ContextPopException, RequestContext, BaseContext, Context, ContextPopException, RequestContext,
@ -712,7 +712,7 @@ class FilterExpression:
# First argument, filter input, is implied. # First argument, filter input, is implied.
plen = len(provided) + 1 plen = len(provided) + 1
# Check to see if a decorator is providing the real function. # Check to see if a decorator is providing the real function.
func = getattr(func, '_decorated_function', func) func = unwrap(func)
args, _, _, defaults, _, _, _ = getfullargspec(func) args, _, _, defaults, _, _, _ = getfullargspec(func)
alen = len(args) alen = len(args)

View File

@ -9,4 +9,5 @@ Django 2.0.6 fixes several bugs in 2.0.5.
Bugfixes Bugfixes
======== ========
* ... * Fixed a regression that broke custom template filters that use decorators
(:ticket:`29400`).

View File

@ -3,6 +3,7 @@ import operator
from django import template from django import template
from django.template.defaultfilters import stringfilter from django.template.defaultfilters import stringfilter
from django.utils.html import escape, format_html from django.utils.html import escape, format_html
from django.utils.safestring import mark_safe
register = template.Library() register = template.Library()
@ -13,6 +14,13 @@ def trim(value, num):
return value[:num] return 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 @register.filter
def noop(value, param=None): def noop(value, param=None):
"""A noop filter that always return its first argument and does nothing with """A noop filter that always return its first argument and does nothing with

View File

@ -25,6 +25,11 @@ class CustomFilterTests(SimpleTestCase):
"abcde" "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): class TagTestCase(SimpleTestCase):