views:

77

answers:

1

Here is a django models file that is not working as I would expect. I would expect the to_url method to do the reverse lookup in the urls.py file, and get a url that would correspond to calling that view with arguments supplied by the Arguments model.

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)

The value d ends up as a dictionary from a unicode string to another unicode string, which I believe, should work fine with the reverse() method that would be called by the permalink decorator, however, it results in:

TypeError: reverse() keywords must be strings
+3  A: 

In your to_url method, you need to make sure the keys in the d dict are not Unicode strings. This isn't peculiar to Django, it's just how keyword arguments to functions work in Python. Here's a simple example:

>>> 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'}

Changing your

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

into something like

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

should do the trick.

Will McCutchen