4

I'm trying to add slugs to the url in my django app, much like SO does.

Currently, I have pages that work just fine with a url like this:

http://example.com/foo/123/

I'd like to add 'slugified' urls like so:

http://example.com/foo/123/foo-name-here

I can get it to work just fine, by simply modifying the urlconf and adding a throwaway value to the view function:

#urls.py

ulpatterns = patterns('project.app.views',
    url(r'^foo/(?P<foo_id>\d+)/(?P<name_slug>\w+)/$', 'foo_detail', name='foo_detail'),
)

#views.py:

def foo_detail(request, foo_id, name_slug):
    # stuff here, name slug is just discarded

Visting the url with the slug works just fine.

However, my problem is when I am using @models.permalink.

For my Foo model, I used to have the following, which worked just fine:

@models.permalink
def get_absolute_url(self):
    return ('foo_detail', [str(self.id),])

However, after my change, whenever I call {{ foo.get_absolute_url }} in my templates, the result is always an empty string.

I have tried the following two replacements for get_absolute_url, neither of which is working:

from django.template.defaultfilters import slugify

# attempt 1
@models.permalink
def get_absolute_url(self):
    return ('foo_detail', [str(self.id), slugify(self.name)])

# attempt 2
@models.permalink
def get_absolute_url(self):
    return ('foo_detail', (), {
        'foo_id': str(self.id), 
        'name_slug': slugify(self.name),
    })

Note that if I add a print slugify(self.name) before returning, the slugified name is showing up in the console just fine.

When invoking {{ foo.get_absolute_url }} in my templates, the result is always an empty string, and I don't get any errors.

I know I could replace the method with return '/foo/%s/%s' % (str(self.id), slugify(self.name)), but I'm trying to get the permalink working so that my URL is only defined in one place. What am I doing wrong?

TM.
  • 108,298
  • 33
  • 122
  • 127
  • 1
    I should note that the way I was doing this is kind've weird and unnecessary: there's no reason I needed to keep `name_slug` in the urlconf or the view function. After the answerer pointed out my problem i was able to go back to `r'^foo/(?P\d+)/([\w-]+)/$'` and `foo_detail(request, foo_id):` respectively, which is cleaner. – TM. Oct 15 '09 at 02:05
  • which permalink method did you end up using ? I am looking at the same thing ... – thornomad Oct 20 '09 at 00:34
  • @thornomad attempt #1 in my question was what I ended up with. turns out there was no problem with the `get_absolute_url` methods I had, just with my url pattern. – TM. Oct 20 '09 at 01:34

1 Answers1

7

One thing to check for, because I also ran into this problem:

(?P<name_slug>\w+)

Is slugify adding hyphens anywhere? If so the regex won't match, hypens are a non-word character. To fix use [\w-]+ or similar.

Dominic Rodger
  • 97,747
  • 36
  • 197
  • 212
Ben Regenspan
  • 10,058
  • 2
  • 33
  • 44