How do I perform a view lookup with a pk and subsequently redirect to a url with the correct slug? (django)

StackOverflow https://stackoverflow.com/questions/19283483

سؤال

I'm trying to configure my app's routing such that the appropriate view page is looked up via the pk, and it returns a redirect with the proper url that has the correct slug following.

For example, I have the model Post with the title and slug fields. Let's say I have a Post object with the pk 1 and slug hello-world. What I would like to happen is that you will be redirected to /post/1/hello-world/, whether I navigate to:

  • /post/1/
  • /post/1/hello-world/, or
  • /post/1/wrong-slug/

The reason why I would like to do this is so that if I happen to update this post's slug to, say, hello-world-revised, going to /post/1/hello-world/ will (a) still return the correct view, and (b) redirect to the updated/correct url (aka /post/1/hello-world-revised/).

I have this in my app's urls.py:

urlpatterns = patterns('', 
    ...
    url(r'^(?P<post_id>\d+)(?:/(?P<slug>[\w\d-]+))?/$', views.post, name='blog-post'),
)

And in views.py:

def post(request, post_id, slug):
    post = get_object_or_404(Post, pk=post_id)
    return render(request, 'blog/post.html', {'post': post})

This gets me (a) above (retrieving the correct view), but not (b). To try and achieve (b), I have tried:

  • Performing a redirect in my post view:

    def post(request, post_id, slug):
        post = get_object_or_404(Post, pk=post_id)
        return redirect('blog-post', post.id, post.slug)
    

    But when I navigate to any post, I get the "This webpage has a redirect loop" error.

  • Overriding the get_absolute_url method on my Post model (following the pattern described in this question):

    class Post(models.Model):
        ...
    
        @models.permalink
        def get_absolute_url(self):
            kwargs = {
                'post_id': str(self.id),
                'slug': self.slug,
            )
            return ('blog-post', (), kwargs)
    

    But that didn't have any effect; the correct view returned, but the URL remained as whatever you had typed in initially.

Does anyone know how to get this working?

هل كانت مفيدة؟

المحلول

I think you are missing a condition in your redirect:

def post(request, post_id, slug):
    post = get_object_or_404(Post, pk=post_id)
    if slug != post.slug
        return redirect('blog-post', post.id, post.slug)
    else:
        return render(request, 'blog/post.html', {'post': post})
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top