django generics seo views

Redirigir desde la vista genérica Vista detallada en Django



generics seo (2)

Estoy usando la vista genérica DetailView basada en clase de Django para buscar un objeto para mostrar. Bajo ciertas circunstancias, en lugar de mostrar el objeto, deseo retroceder y emitir un rediect HTTP en su lugar. No puedo ver cómo hago para hacer esto. Es para cuando un usuario golpea un objeto en mi aplicación, pero sin usar la URL canónica. Así, por ejemplo, en las URL de StackOverflow toman la forma:

http://stackoverflow.com/<content_type>/<pk>/<seo_friendly_slug>

p.ej:

http://stackoverflow.com/questions/5661806/django-debug-toolbar-with-django-cms-and-django-1-3

Puede escribir cualquier cosa como parte de seo_friendly_slug y le redirigirá a la URL canónica correcta para el objeto buscado a través de la PK.

Deseo hacer lo mismo en mi DetailView. Recupere el objeto, verifique que sea la URL canónica y, si no, redirija a la URL get_absolute_url del elemento.

No puedo devolver un HttpResponseRedirect en get_object, ya que está esperando el objeto buscado. Parece que no puedo devolverlo desde get_context_data, ya que solo está esperando datos de contexto.

Tal vez solo necesito escribir una vista manual, pero me pregunto si alguien sabía si era posible.

¡Gracias!

Ludo.


Al desarrollar la respuesta y los comentarios de Rolo, se me ocurrió la siguiente vista genérica para cumplir este propósito:

from django import http from django.views import generic class CanonicalDetailView(generic.DetailView): """ A DetailView which redirects to the absolute_url, if necessary. """ def get_object(self, *args, **kwargs): # Return any previously-cached object if getattr(self, ''object'', None): return self.object return super(CanonicalDetailView, self).get_object(*args, **kwargs) def get(self, *args, **kwargs): # Make sure to use the canonical URL self.object = self.get_object() obj_url = self.object.get_absolute_url() if self.request.path != obj_url: return http.HttpResponsePermanentRedirect(obj_url) return super(CanonicalDetailView, self).get(*args, **kwargs);

Esto se usa de la misma manera que el DetailView normal, y debería funcionar para cualquier modelo que implemente get_absolute_url correctamente.


Esto no es un ajuste natural para DetailView. Para hacer esto, necesita anular el método get de BaseDetailView, que se ve así:

class BaseDetailView(SingleObjectMixin, View): def get(self, request, **kwargs): self.object = self.get_object() context = self.get_context_data(object=self.object) return self.render_to_response(context)

Por lo tanto, en su clase, deberá proporcionar un nuevo método de obtención que verifique la URL entre la obtención del objeto y la configuración del contexto. Algo como:

def get(self, request, **kwargs): self.object = self.get_object() if self.request.path != self.object.get_absolute_url(): return HttpResponseRedirect(self.object.get_absolute_url()) else: context = self.get_context_data(object=self.object) return self.render_to_response(context)

A medida que terminas anulando gran parte de la funcionalidad, se vuelve cuestionable si vale la pena usar una vista genérica para esto, pero lo sabes.