I want to use the same url model as SO. The lookup is done through the id number but if the wrong slug is in the link than a redirect is thrown to the correct page.
example: questions/4787731/whatever will redirect to questions/4787731/canonical-links-and-301-redirect-if-url-doesnt-match-slug. My current code does the lookup through the id but does not redirect in case of a bad slug. example: entities/12786676/whatever should redirect to /entities/12786676/yellow-and-green-tree/. I do get the content of the page correctly but I want also the url to be redirected to avoid bad links. Here is the code:
views:
class EntityRedirectDetailView(RedirectView):
def get(self, request, *args, **kwargs):
pk = self.kwargs.get('pk', None)
slug=self.kwargs.get('slug', None)
entity = EntitiesNew.objects.get(pk=pk)
self.url = '/entities/%s/%s' % (entity.pk, entity.slug)
return super(EntityRedirectDetailView, self).get(request, *args, **kwargs)
urls:
urlpatterns = [
url(r'^$', ListView.as_view(context_object_name = 'entities_list', queryset=EntitiesNew.objects.order_by('-id_number')[:500]), name='entities'),
url(r'^(?P<pk>\d+)/$', views.EntityRedirectDetailView.as_view(), name='entities-redirect'),
url(r'^(?P<pk>\d+)(?:/(?P<slug>[\w\d-]+))?/$', DetailView.as_view( model=EntitiesNew, context_object_name="entity"), name="entities-detail"),
]
thanks
Ok I managed to do what I wanted by overriding the get method in my EntityDetailView(Detailview) as per Paulo Almeida's suggestion. Here is the final code.
urls.py:
url(r'^(?P<pk>\d+)/$', views.EntityRedirectDetailView.as_view(), name='entities-redirect'),
url(r'^(?P<pk>\d+)/(?P<slug>[-\w\d]+)/$', views.EntityDetailView.as_view(), name="entities-detail"),
views.py
class EntityRedirectDetailView(RedirectView):
def get(self, request, *args, **kwargs):
pk = self.kwargs.get('pk', None)
slug=self.kwargs.get('slug', None)
entity = EntitiesNew.objects.get(pk=pk)
self.url = '/entities/%s/%s' % (entity.pk, entity.slug)
return super(EntityRedirectDetailView, self).get(request, *args, **kwargs)
class EntityDetailView(generic.DetailView):
"""
A DetailView which redirects to the absolute_url, if necessary.
"""
template_name = 'entities/entitiesnew_detail.html'
queryset = EntitiesNew.objects.get_queryset()
def get_object(self, *args, **kwargs):
# Return any previously-cached object
pk = self.kwargs.get('pk', None)
entity=EntitiesNew.objects.get(pk=pk)
if getattr(self, 'entity', None):
return self.entity
return super(EntityDetailView, self).get_object(*args, **kwargs)
def get(self, *args, **kwargs):
# Make sure to use the canonical URL
self.entity = self.get_object()
obj_url = self.entity.get_absolute_url()
if self.request.path != obj_url:
return http.HttpResponsePermanentRedirect(obj_url)
return super(EntityDetailView, self).get(*args, **kwargs);
in models.py I have the get_absoulte_url:
def get_absolute_url(self):
return reverse('entities:entities-detail', kwargs={'pk':self.pk, 'slug':self.slug})
and in the template: {% url 'entities:entities-detail' entitiesnew.pk entitiesnew.slug %}