Shortcut Decorator


Coding , ,


Ist es nicht manchmal nervig bei Django in views render_to_response aufzurufen, und gegf. sogar noch den Context? Vor kurzem brauchte ich den Template Processor django.core.context_processors.auth, um auf die Session Variable “user” zuzugreifen


In generic views ist dies ja bereits automatisch der fall, dass die Variable im Template verfuegbar ist. Bei normalen views muss man allerdings jeweils den richtigen Context angeben, wie z.B. mit

def myview(request):
  ...
  return render_to_response("template.html",
    context_instance=RequestContext(request))

Das kann mit der Zeit ziemlich nervig werden. Mit folgendem Decorator kann man sich das Leben erheblich leichert machen:

from django.template.context import RequestContext
from django.http import HttpResponse
from django.shortcuts import render_to_response
 
def page(template=None, **decorator_args):
  def _wrapper(fn):
    def _innerWrapper(request, *args, **kw):
      context_dict = decorator_args.copy()
      g = fn(request, *args, **kw)
      if not hasattr(g, 'next'): 
        g = (g,)
        for i in g:
          if isinstance(i, HttpResponse):
            return i
          if type(i) == type(()):
            context_dict[i[0]] = i[1]
          else:
            context_dict.update(i)
        template_name = context_dict.get("template",  template)
        context_instance = RequestContext(request)
        return render_to_response(template_name, context_dict, context_instance)
    return _innerWrapper
  return _wrapper

Dadurch kann man bei einem view per Decorator direkt das Template angeben, ohne render_to_response aufzrufen:

@page("template.html")
def myview(request):
  somedata = Data.objects.all()
  yield {'data': somedata}

Aber das ist noch nicht alles…

@page("template.html", title="Titel der Seite") # extra Argument fuer den Context
def myview(request):
  somedata = Data.objects.all()
  yield locals() # lokale Variable werden an den Context uebergeben, in  diesem Fall somedata

Das Template muss auch nicht umbedingt im Decorator angegeben werden…

@page()
def myview(request):
  somedata = Data.objects.all()
  template = "template2.html"
  yield locals() # lokale Variable werden an den Context uebergeben, in  diesem Fall somedata

Cool oder? :-)



Kommentar hinzufügen