﻿id	summary	reporter	owner	description	type	status	component	version	severity	resolution	keywords	cc	stage	has_patch	needs_docs	needs_tests	needs_better_patch	easy	ui_ux
393	[patch] Filters don't take the str() value of a var	Boffbowsh	Adrian Holovaty	"If I have a category model and do {{category|upper}} it fails, even though i have a __repr__(). Added str() to a number of filters to fix this behaviour. Maybe would be better to add to the template definition what sort of var it should accept? If it only accepts strings, str() everything first within django.core.template[[br]]
Also added basic tests to string filters that don't accept args

{{{
Index: /usr/local/django_src/django/core/defaultfilters.py
===================================================================
--- /usr/local/django_src/django/core/defaultfilters.py	(revision 544)
+++ /usr/local/django_src/django/core/defaultfilters.py	(working copy)
@@ -9,7 +9,7 @@
 
 def addslashes(value, _):
     ""Adds slashes - useful for passing strings to JavaScript, for example.""
-    return value.replace('""', '\\""').replace(""'"", ""\\'"")
+    return str(value).replace('""', '\\""').replace(""'"", ""\\'"")
 
 def capfirst(value, _):
     ""Capitalizes the first character of the value""
@@ -19,7 +19,7 @@
 def fix_ampersands(value, _):
     ""Replaces ampersands with ``&amp;`` entities""
     from django.utils.html import fix_ampersands
-    return fix_ampersands(value)
+    return fix_ampersands(str(value))
 
 def floatformat(text, _):
     """"""
@@ -35,7 +35,7 @@
 def linenumbers(value, _):
     ""Displays text with line numbers""
     from django.utils.html import escape
-    lines = value.split('\n')
+    lines = str(value).split('\n')
     # Find the maximum width of the line count, for use with zero padding string format command
     width = str(len(str(len(lines))))
     for i, line in enumerate(lines):
@@ -44,7 +44,7 @@
 
 def lower(value, _):
     ""Converts a string into all lowercase""
-    return value.lower()
+    return str(value).lower()
 
 def make_list(value, _):
     """"""
@@ -55,7 +55,7 @@
 
 def slugify(value, _):
     ""Converts to lowercase, removes non-alpha chars and converts spaces to hyphens""
-    value = re.sub('[^\w\s-]', '', value).strip().lower()
+    value = re.sub('[^\w\s-]', '', str(value)).strip().lower()
     return re.sub('\s+', '-', value)
 
 def stringformat(value, arg):
@@ -74,7 +74,7 @@
 
 def title(value, _):
     ""Converts a string into titlecase""
-    return re.sub(""([a-z])'([A-Z])"", lambda m: m.group(0).lower(), value.title())
+    return re.sub(""([a-z])'([A-Z])"", lambda m: m.group(0).lower(), str(value).title())
 
 def truncatewords(value, arg):
     """"""
@@ -93,17 +93,17 @@
 
 def upper(value, _):
     ""Converts a string into all uppercase""
-    return value.upper()
+    return str(value).upper()
 
 def urlencode(value, _):
     ""Escapes a value for use in a URL""
     import urllib
-    return urllib.quote(value)
+    return urllib.quote(str(value))
 
 def urlize(value, _):
     ""Converts URLs in plain text into clickable links""
     from django.utils.html import urlize
-    return urlize(value, nofollow=True)
+    return urlize(str(value), nofollow=True)
 
 def urlizetrunc(value, limit):
     """"""
@@ -116,7 +116,7 @@
 
 def wordcount(value, _):
     ""Returns the number of words""
-    return len(value.split())
+    return len(str(value).split())
 
 def wordwrap(value, arg):
     """"""
@@ -163,11 +163,11 @@
 def linebreaks(value, _):
     ""Converts newlines into <p> and <br />s""
     from django.utils.html import linebreaks
-    return linebreaks(value)
+    return linebreaks(str(value))
 
 def linebreaksbr(value, _):
     ""Converts newlines into <br />s""
-    return value.replace('\n', '<br />')
+    return str(value).replace('\n', '<br />')
 
 def removetags(value, tags):
     ""Removes a space separated list of [X]HTML tags from the output""
@@ -410,7 +410,7 @@
 def phone2numeric(value, _):
     ""Takes a phone number and converts it in to its numerical equivalent""
     from django.utils.text import phone2numeric
-    return phone2numeric(value)
+    return phone2numeric(str(value))
 
 def pprint(value, _):
     ""A wrapper around pprint.pprint -- for debugging, really""
}}}
{{{
Index: /usr/local/django_src/tests/othertests/templates.py
===================================================================
--- /usr/local/django_src/tests/othertests/templates.py	(revision 544)
+++ /usr/local/django_src/tests/othertests/templates.py	(working copy)
@@ -1,4 +1,4 @@
-from django.core import template, template_loader
+from django.core import template, template_loader, defaultfilters
 
 # Helper objects for template tests
 class SomeClass:
@@ -10,6 +10,9 @@
         
     def method2(self, o):
         return o
+	
+    def __repr__(self):
+	return 'DjAnGo'
 
 class OtherClass:
     def method(self):
@@ -166,6 +169,25 @@
     'exception04': (""{% extends 'inheritance17' %}{% block first %}{% echo 400 %}5678{% endblock %}"", {}, template.TemplateSyntaxError),
 }
 
+STRING_FILTERS = (
+	'linebreaksbr',
+	'striptags',
+	'escape',
+	'linebreaks',
+	'urlize',
+	'fix_ampersands',
+	'title',
+	'capfirst',
+	'wordcount',
+	'linenumbers',
+	'urlencode',
+	'lower',
+	'upper',
+	'phone2numeric',
+	'addslashes',
+	'slugify'
+	)
+
 # This replaces the standard template_loader.
 def test_template_loader(template_name, template_dirs=None):
     try:
@@ -176,6 +198,8 @@
 def run_tests(verbosity=0, standalone=False):
     template_loader.load_template_source, old_template_loader = test_template_loader, template_loader.load_template_source
     failed_tests = []
+    for stringfilter in STRING_FILTERS:
+	    TEMPLATE_TESTS['filter_' + stringfilter] = ( '{{ var|%s }}' % stringfilter, {""var"": SomeClass()}, str(defaultfilters.template.registered_filters[stringfilter][0](str( 'DjAnGo' ), ())) )
     tests = TEMPLATE_TESTS.items()
     tests.sort()
     for name, vals in tests:
}}}"	enhancement	closed	Core (Other)		critical	fixed			Ready for checkin	1	0	0	0	0	0
