Opened 15 years ago
Closed 15 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 , 15 years ago
Attachment: | template.py added |
---|
by , 15 years ago
Attachment: | template_v2.py added |
---|
Modified "template" decorator. Now uses RequestContext instead of standard Context
comment:1 by , 15 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