为什么Django的reverse()在处理Unicode时失败?

3 投票
1 回答
835 浏览
提问于 2025-04-15 21:51

这里有一个Django模型文件,它的表现并没有我预期的那样。
我本来希望to_url这个方法能在urls.py文件中进行反向查找,获取一个对应于用Arguments模型提供的参数调用那个视图的URL。

from django.db import models
class Element(models.Model):
    viewname = models.CharField(max_length = 200)
    arguments = models.ManyToManyField('Argument', null = True, blank = True )

    @models.permalink
    def to_url(self):
        d = dict( self.arguments.values_list('key', 'value') )
        return (self.viewname, (), d)
class Argument(models.Model):
    key = models.CharField(max_length=200)
    value = models.CharField(max_length=200)

最后,值d变成了一个从Unicode字符串到另一个Unicode字符串的字典。我认为,这样应该可以和permalink装饰器调用的reverse()方法正常工作,但结果却是:

TypeError: reverse() keywords must be strings

1 个回答

5

在你的 to_url 方法中,你需要确保 d 字典里的键不是 Unicode 字符串。这并不是 Django 特有的情况,而是 Python 中函数的关键字参数工作方式的一个特点。下面是一个简单的例子:

>>> def f(**kwargs): print kwargs
... 
>>> d1 = { u'foo': u'bar' }
>>> d2 = { 'foo': u'bar' }
>>> f(**d1)
TypeError: f() keywords must be strings
>>> f(**d2)
{'foo': u'bar'}

把你的

d = dict( self.arguments.values_list('key', 'value') )

改成类似下面这样的

d = dict((str(k), v) for k, v in self.arguments.values_list('key', 'value').iteritems())

应该就能解决问题了。

撰写回答