How can I make an URL scheme that works just like Stackoverflow?
This isn't the same question as this one, though it is similar. The difference is that I want an URL scheme that implements all of Stackoverflow's cleverness, and allows reverse
ing to generate fully slugged URLs.
Specifically, the Stackoverflow behaviour to mimic:
- Lookup by id only, with slug only for SEO/readability purposes
Forwarding to correct slug when the incorrect slug, or no slug is given. e.g. if I have an object
123
with a nameMy Object Name
:/123/ redirects to /123/my-object-name/ /123/something/ redirects to /123/my-object-name/
If I change the object name to
My New Object Name
then the redirect target slug changes accordingly (this is Stackoverflow's behaviour, if you edit your question's title), e.g.:/123/my-object-name/ redirects to /123/my-new-object-name/
- Reverse working so that
{% url 'my_view' 123 %}
returns/123/my-object-name/
, and after editing the object name, returns/123/my-new-object-name/
I've hacked something whereby I use a models.py
:
class MyModel(models.Model):
name = models.CharField(max_length=70)
def my_slugged_url(self):
slug = slugify(self.name)
if slug:
return reverse('my_view', args=[self.id]) + slug + "/"
return reverse('my_view', args=[self.id])
...and a urls.py
pattern:
url(r'^(\d+)/\S+/$', 'my_view')
url(r'^(\d+)/$', 'my_view'),
...and a views.py
:
def my_view(request, id):
obj = get_object_or_404(MyModel, pk=id)
if request.path != obj.my_slugged_url():
return redirect(obj.my_slugged_url())
...but this feels wrong, and means when I do a reverse
or {% url 'my_view' 123 %}
it returns a URL like /123/
that then has to redirect to /123/my-object-name
.
How can I make this work just like Stackoverflow?