title: How can I make Stackoverflow-style URLs in Django with a working reverse, that allow the slug to change?
body: <p>How can I make an URL scheme that works just like Stackoverflow?</p>
  
  <p>This isn't the same question as <a href="https://stackoverflow.com/questions/2339436/how-can-i-make-urls-in-django-similar-to-stackoverflow">this one</a>, though it is similar. The difference is that I want an URL scheme that implements all of Stackoverflow's cleverness, and allows <code>reverse</code>ing to generate fully slugged URLs.</p>
  
  <p>Specifically, the Stackoverflow behaviour to mimic:</p>
  
  <ol>
  <li>Lookup by id only, with slug only for SEO/readability purposes</li>
  <li><p>Forwarding to correct slug when the incorrect slug, or no slug is given. e.g. if I have an object <code>123</code> with a name <code>My Object Name</code>:</p>
  
  <pre><code>/123/ redirects to /123/my-object-name/
  /123/something/ redirects to /123/my-object-name/
  </code></pre></li>
  <li><p>If I change the object name to <code>My New Object Name</code> then the redirect target slug changes accordingly (this is Stackoverflow's behaviour, if you edit your question's title), e.g.:</p>
  
  <pre><code>/123/my-object-name/ redirects to /123/my-new-object-name/
  </code></pre></li>
  <li>Reverse working so that <code>{% url 'my_view' 123 %}</code> returns <code>/123/my-object-name/</code>, and after editing the object name, returns <code>/123/my-new-object-name/</code></li>
  </ol>
  
  <p>I've hacked something whereby I use a <code>models.py</code>:</p>
  
  <pre><code>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])
  </code></pre>
  
  <p>...and a <code>urls.py</code> pattern:</p>
  
  <pre><code>url(r'^(\d+)/\S+/$', 'my_view')
  url(r'^(\d+)/$', 'my_view'),
  </code></pre>
  
  <p>...and a <code>views.py</code>:</p>
  
  <pre><code>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())
  </code></pre>
  
  <p>...but this feels wrong, and means when I do a <code>reverse</code> or <code>{% url 'my_view' 123 %}</code> it returns a URL like <code>/123/</code> that then has to redirect to <code>/123/my-object-name</code>.</p>
  
  <p>How can I make this work just like Stackoverflow?</p>