Opened 16 years ago
Closed 16 years ago
#12329 closed (wontfix)
"template" view decorator, allows to completely isolate views from templates
| Reported by: | gurunars | Owned by: | nobody |
|---|---|---|---|
| Component: | Uncategorized | Version: | 1.1 |
| Severity: | Keywords: | ||
| Cc: | Triage Stage: | Unreviewed | |
| Has patch: | no | Needs documentation: | no |
| Needs tests: | no | Patch needs improvement: | no |
| Easy pickings: | no | UI/UX: | no |
Description
Well, the key point of this decorator is to let the developer define a template for the view in the following way:
@template
def view_name(request):
...
OR
@template("template_name")
def view_name(request):
...
In the first case the decorator automatically composes template's name in the following way: "app_name/view_name.html". This is the same name you would use in a "render_to_response" shortcut function.
In the second case you define template's name explicitly. Again use the same name you would use for the "render_to_response" shortcut function.
In both cases the return type can be either a dictionary, an HttpResponse or an HttpResponseHolder. The last one is just an extension to HttpResponse base class - it has just a single additional parameter called "context" (it is a dictionary). The only purpose of HttpResponseHolder is to pass a context dictionary to some other decorators for further processing. What kind of processing? I will give some examples below.
First example is quite trivial. How to pass the "MEDIA_PATH" parameter from "settings.py" to all the templates? In this case it is really simple - use a decorator as the one just below
from django.conf import settings
from .template import *
class media(object):
def __init__(self, orig_func):
self.orig_func = orig_func
#to compose template's name properly
self.__name__ = self.orig_func.__name__
self.__module__ = self.orig_func.__module__
def __call__(self, *args, **kwargs):
return_val = self.orig_func(*args, **kwargs)
if isinstance(return_val, HttpResponseHolder):
return_val.context["MEDIA_URL"] = settings.MEDIA_URL
elif isinstance(return_val, dict):
return_val["MEDIA_URL"] = settings.MEDIA_URL
return return_val
in chain with the "template" decorator
@template()
@media
def view_name(request):
...
Second example is little bit more sophisticated but useful. How to pass to the template information about the user that is currently logged in (user object)? Use the following decorator
from .template import * #HttpResponseHolder
class user(object):
def __init__(self, orig_func):
self.orig_func = orig_func
#to compose template's name properly
self.__name__ = self.orig_func.__name__
self.__module__ = self.orig_func.__module__
def __call__(self, request, *args, **kwargs):
return_val = self.orig_func(request, *args, **kwargs)
if request.user:
if isinstance(return_val, HttpResponseHolder):
return_val.context["user"] = request.user
elif isinstance(return_val, dict):
return_val["user"] = request.user
return return_val
again in chain with the "template" decorator
@template()
@user
def view_name(request):
...
Definitely, writing your own decorators requires some skills in Python. But once done they simplify your life a lot.
Attachments (2)
Change History (3)
by , 16 years ago
| Attachment: | template.py added |
|---|
by , 16 years ago
| Attachment: | template_v2.py added |
|---|
Modified "template" decorator. Now uses RequestContext instead of standard Context
comment:1 by , 16 years ago
| Resolution: | → wontfix |
|---|---|
| Status: | new → closed |
This has been requested several times, and rejected. I (and others in the core) simply don't see that using decorators in this way makes anything clearer.
The current contract for a view is that it accepts a request, returns a response. If you use a decorator to modify templates, this contract becomes "returns a response, or a response holder, or a dictionary". This isn't an improvement.
An alternate proposal that *does* have some support in the core is the idea of a TemplateResponse - that is, that you can return a response whose template will be lazily evaluated, allowing decorators, middlewares, or view wrappers to modify the template that is used. This means a view can return a template and a context, but the actual template that is used can be modified by something higher up in the chain. For details, see ticket #12815.
The source code of the decorator