Parámetros y lógica de URL en las vistas basadas en clases de Django (TemplateView)

No me queda claro cómo es mejor acceder a los parámetros de URL en las vistas basadas en clase en Django 1.5.

Considera lo siguiente:

Ver:

from django.views.generic.base import TemplateView class Yearly(TemplateView): template_name = "calendars/yearly.html" current_year = datetime.datetime.now().year current_month = datetime.datetime.now().month def get_context_data(self, **kwargs): context = super(Yearly, self).get_context_data(**kwargs) context['current_year'] = self.current_year context['current_month'] = self.current_month return context 

URLCONF:

 from .views import Yearly urlpatterns = patterns('', url( regex=r'^(?P\d+)/$', view=Yearly.as_view(), name='yearly-view' ), ) 

Quiero acceder al parámetro del year en mi vista, por lo que puedo hacer lógica como:

 month_names = ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"] for month, month_name in enumerate(month_names, start=1): is_current = False if year == current_year and month == current_month: is_current = True months.append({ 'month': month, 'name': month_name, 'is_current': is_current}) 

¿Cómo podría uno acceder mejor al parámetro url en los CBV como el anterior que está subclasificado de TemplateView y dónde debería ubicarse idealmente la lógica de esta manera, por ejemplo? en un metodo?

Para acceder a los parámetros de url en vistas basadas en clases, use self.args o self.kwargs para que acceda a él haciendo self.kwargs['year']

En caso de que pase un parámetro de URL como este:

 http:///?order_by=created 

Puede acceder a él en la vista basada en clase utilizando self.request.GET (no se presenta en self.args ni en self.kwargs ):

 class MyClassBasedView(ObjectList): ... def get_queryset(self): order_by = self.request.GET.get('order_by') or '-created' qs = super(MyClassBasedView, self).get_queryset() return qs.order_by(order_by) 

Encontré esta solución elegante, y para django 1.5 o superior, como se indica aquí :

Las vistas basadas en la clase genérica de Django ahora incluyen automáticamente una variable de vista en el contexto. Esta variable apunta a su objeto de vista.

En su views.py:

 from django.views.generic.base import TemplateView class Yearly(TemplateView): template_name = "calendars/yearly.html" # No here current_year = datetime.datetime.now().year current_month = datetime.datetime.now().month # dispatch is called when the class instance loads def dispatch(self, request, *args, **kwargs): self.year = kwargs.get('year', "any_default") # other code # needed to have an HttpResponse return super(Yearly, self).dispatch(request, *args, **kwargs) 

La solución de despacho encontrada en esta pregunta .
Como la vista ya se pasa dentro del contexto de la Plantilla, no es necesario que se preocupe por ella. En su archivo de plantilla anual.html, es posible acceder a esos atributos de vista simplemente mediante:

 {{ view.year }} {{ view.current_year }} {{ view.current_month }} 

Puedes mantener tu urlconf como es.

Es bueno mencionar que obtener información en el contexto de su plantilla sobrescribe el get_context_data (), por lo que de alguna manera está rompiendo el flujo de bean de acción del django.

Hasta ahora solo he podido acceder a estos parámetros de URL desde el método get_queryset, aunque solo lo he probado con un ListView no con TemplateView. Usaré el parámetro url para crear un atributo en la instancia del objeto, luego usaré ese atributo en get_context_data para rellenar el contexto:

 class Yearly(TemplateView): template_name = "calendars/yearly.html" current_year = datetime.datetime.now().year current_month = datetime.datetime.now().month def get_queryset(self): self.year = self.kwargs['year'] queryset = super(Yearly, self).get_queryset() return queryset def get_context_data(self, **kwargs): context = super(Yearly, self).get_context_data(**kwargs) context['current_year'] = self.current_year context['current_month'] = self.current_month context['year'] = self.year return context 

¿Qué tal si solo usas decoradores de Python para hacer esto inteligible?

 class Yearly(TemplateView): @property def year(self): return self.kwargs['year']