Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Django slug and id as URL redirect

Tags:

python

django

I'm trying to get something in Django, already for hours but without success. However I'm trying to use friendly urls like 'my-post-title-1234', where the number at the end is the post's id and the rest before that is the post's title. I got the url by using the slug and the id and I can retrive both in the view. So I check if ID exists and if it exists I do the rest, and if it doesn't exist I do 404 DoesNotExist. Inside the model I generated slug field and slugified title.

Everything works so far except one thing: User is able to write bla-bla-bla-1234 and it will still show him same data (since id exist). What I would like is following:

If user type in 'bla-bla-bla-1234' I would like to redirect him to correct slug 'my-post-title-1234'.

This is how my url looks like:

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

This is my model:

class Post(models.Model):
    post_title = models.CharField(max_length = 125)
    text = models.TextField()
    slug = models.SlugField(null = False, blank = True)
    def __str__(self):
        return self.post_title
    def save(self, *args, **kwargs):
        self.slug = slugify(self.post_title)
        super(Post, self).save(*args, **kwargs)

This is from my view:

def post(request, slug, post_id):
    try:
        post = Post.objects.get(id = post_id)
    except Post.DoesNotExist:
        raise Http404("Post does not exist")
    return HttpResponse(post_id)

So the question is: how do I redirect(change url) to the correct slug from 'bla-bla-bla-1234' to 'my-post-title-1234', if user type in slug incorrectly while id is still good.

Thanks a lot.

like image 775
bernadd Avatar asked Oct 12 '15 17:10

bernadd


1 Answers

Seems like you just need to check if the slug is correct, and if not do a redirect.

from django.shortcuts import get_object_or_404, redirect

def post(request, slug, post_id):
    obj = get_object_or_404(Post, pk=post_id)
    if obj.slug != slug:
        return redirect('post', slug=obj.slug, post_id=obj.pk)

Note that there's a built-in shortcut for your first four lines: get_object_or_404. Also, be aware that calling an object within the function the same name as the function itself can lead to confusion; avoid doing that (which is why I've use obj above.)

like image 72
Daniel Roseman Avatar answered Oct 03 '22 03:10

Daniel Roseman