Index: tests/regressiontests/templates/tests.py
===================================================================
--- tests/regressiontests/templates/tests.py	(revision 12494)
+++ tests/regressiontests/templates/tests.py	(working copy)
@@ -1031,11 +1031,20 @@
             'url08': (u'{% url метка_оператора v %}', {'v': 'Ω'}, '/url_tag/%D0%AE%D0%BD%D0%B8%D0%BA%D0%BE%D0%B4/%CE%A9/'),
             'url09': (u'{% url метка_оператора_2 tag=v %}', {'v': 'Ω'}, '/url_tag/%D0%AE%D0%BD%D0%B8%D0%BA%D0%BE%D0%B4/%CE%A9/'),
             'url10': ('{% url regressiontests.templates.views.client_action id=client.id,action="two words" %}', {'client': {'id': 1}}, '/url_tag/client/1/two%20words/'),
+            'url11': ('{% url regressiontests.templates.views.client_action id=client.id,action="==" %}', {'client': {'id': 1}}, '/url_tag/client/1/==/'),
+            'url12': ('{% url regressiontests.templates.views.client_action id=client.id,action="," %}', {'client': {'id': 1}}, '/url_tag/client/1/,/'),
+            'url12': ('{% url regressiontests.templates.views.client_action id=client.id,action=arg|join:"-" %}', {'client': {'id': 1}, 'arg':['a','b']}, '/url_tag/client/1/a-b/'),
 
             # Failures
             'url-fail01': ('{% url %}', {}, template.TemplateSyntaxError),
             'url-fail02': ('{% url no_such_view %}', {}, urlresolvers.NoReverseMatch),
             'url-fail03': ('{% url regressiontests.templates.views.client %}', {}, urlresolvers.NoReverseMatch),
+            'url-fail04': ('{% url view id, %}', {}, template.TemplateSyntaxError),
+            'url-fail05': ('{% url view id= %}', {}, template.TemplateSyntaxError),
+            'url-fail06': ('{% url view a.id=id %}', {}, template.TemplateSyntaxError),
+            'url-fail07': ('{% url view a.id!id %}', {}, template.TemplateSyntaxError),
+            'url-fail08': ('{% url view id="unterminatedstring %}', {}, template.TemplateSyntaxError),
+            'url-fail09': ('{% url view id=", %}', {}, template.TemplateSyntaxError),
 
             # {% url ... as var %}
             'url-asvar01': ('{% url regressiontests.templates.views.index as url %}', {}, ''),
Index: django/template/defaulttags.py
===================================================================
--- django/template/defaulttags.py	(revision 12494)
+++ django/template/defaulttags.py	(working copy)
@@ -7,6 +7,7 @@
 from django.template import Node, NodeList, Template, Context, Variable
 from django.template import TemplateSyntaxError, VariableDoesNotExist, BLOCK_TAG_START, BLOCK_TAG_END, VARIABLE_TAG_START, VARIABLE_TAG_END, SINGLE_BRACE_START, SINGLE_BRACE_END, COMMENT_TAG_START, COMMENT_TAG_END
 from django.template import get_library, Library, InvalidTemplateLibrary
+from django.template import filter_re
 from django.template.smartif import IfParser, Literal
 from django.conf import settings
 from django.utils.encoding import smart_str, smart_unicode
@@ -1118,13 +1119,48 @@
                 asvar = bits.next()
                 break
             else:
-                for arg in bit.split(","):
-                    if '=' in arg:
-                        k, v = arg.split('=', 1)
-                        k = k.strip()
-                        kwargs[k] = parser.compile_filter(v)
-                    elif arg:
-                        args.append(parser.compile_filter(arg))
+                matches = filter_re.finditer(bit)
+                upto = 0
+                while True:
+                    match = filter_re.match(bit[upto:])
+                    if not match:
+                        raise TemplateSyntaxError("Could not parse: %s" % \
+                                bit[upto:])
+                    start, end = match.start()+upto, match.end()+upto
+
+                    if end != len(bit) and bit[end] == '=':
+                        if not match.group("var"):
+                            raise TemplateSyntaxError("Keyword argument must be a variable name: %s" % \
+                                    bit[start:end])
+                        arg_name = match.group("var")
+                        if '.' in arg_name:
+                            raise TemplateSyntaxError("Keyword name must not contain '.': %s" % \
+                                    arg_name)
+                        var_parts, var_end = filter_re.finditer(bit[end+1:]), 0
+
+                        for i, var_part in enumerate(var_parts):
+                            if var_part.start() != var_end:
+                                break
+                            if (i == 0) ^ (var_part.group("filter_name") is None):
+                                raise TemplateSyntaxError("Malformed filter expression: %s" % \
+                                        bits[end+1:])
+                            var_end = var_part.end()
+
+                        if var_end == 0:
+                            raise TemplateSyntaxError("Keyword argument lacks value: %s" % \
+                                    arg_name)
+                        kwargs[arg_name] = parser.compile_filter(bit[end+1:var_end+end+1])
+                        end = var_end + end + 1
+                    else:
+                        args.append(parser.compile_filter(bit[start:end]))
+
+                    if end == len(bit):
+                        break
+                    if bit[end] != ',':
+                        raise TemplateSyntaxError("Arguments must be separated by ',', not '%s'" % \
+                          bit[end:])
+                    upto = end + 1
+
     return URLNode(viewname, args, kwargs, asvar)
 url = register.tag(url)
 
