|
''' |
|
This module introduces viewtag concept: |
|
funcions that act both as template tags and as views. |
|
|
|
Example usage: |
|
|
|
First in urls (once): |
|
url(r'^viewtag/([-\w]+)/$', 'viewtags.view', name='viewtag'), |
|
|
|
and |
|
|
|
viewtags.autodiscover() |
|
|
|
|
|
Then in app/viewtags.py: |
|
|
|
from placeforpeople.viewtags import viewtag, model_arg |
|
|
|
@viewtag('viewtag_test.html', [model_arg('obj', Object)]) # you can use querysets too |
|
def test_viewtag(request, obj, page=0): |
|
return { |
|
'obj': obj, |
|
'page': page, |
|
} |
|
|
|
Later in templates: |
|
{% vt:test_viewtag campaign %} |
|
or |
|
$.get('{% url viewtag "test_viewtag" %}', {page: 2, object: 5}, function(data) { |
|
$('body').append(data); |
|
}); |
|
|
|
''' |
|
import inspect |
|
from django import template |
|
from django.template.loader import get_template |
|
from django.http import Http404 |
|
from django.shortcuts import render_to_response |
|
from django.utils.importlib import import_module |
|
from django.conf import settings |
|
|
|
|
|
register = template.Library() |
|
template.builtins.append(register) |
|
|
|
_viewtags_registry = {} |
|
|
|
|
|
def viewtag(template, args=[]): |
|
def decorator(func): |
|
_register_tag(func, template) |
|
_viewtags_registry[func.__name__] = (func, template, args) |
|
|
|
return func |
|
return decorator |
|
|
|
|
|
def view(request, viewtag_name): |
|
try: |
|
func, template_, arg_processors = _viewtags_registry[viewtag_name] |
|
except KeyError: |
|
raise Http404() |
|
|
|
argnames = inspect.getargspec(func).args |
|
kwargs = {} |
|
for argname in argnames: |
|
if argname in request.REQUEST and argname != 'request': |
|
kwargs[argname] = request.REQUEST[argname] |
|
for proc in arg_processors: |
|
kwargs = proc(request, kwargs) |
|
|
|
return render_to_response(template_, func(request, **kwargs), template.RequestContext(request)) |
|
|
|
def model_arg(key, qs_or_model): |
|
from django.db import models |
|
|
|
if isinstance(qs_or_model, models.base.ModelBase): |
|
qs = qs_or_model._default_manager.all() |
|
else: |
|
qs = qs_or_model |
|
|
|
def processor(request, kwargs): |
|
id = request.REQUEST.get(key) or request.REQUEST.get(key + '_id') |
|
if not id is None: |
|
kwargs[key] = qs.get(id=id) |
|
return kwargs |
|
return processor |
|
|
|
def autodiscover(): |
|
for app in settings.INSTALLED_APPS: |
|
try: |
|
import_module('%s.viewtags' % app) |
|
except ImportError: |
|
pass |
|
|
|
|
|
def _register_tag(func, template): |
|
def tag(parser, token): |
|
parts = token.split_contents() |
|
args, kwargs = [], [] |
|
for part in parts[1:]: |
|
if '=' in part: |
|
kwargs.append(part.split('=', 1)) |
|
else: |
|
args.append(part) |
|
|
|
return TempNode(func, template, args, dict(kwargs)) |
|
register.tag('vt:' + func.__name__, tag) |
|
|
|
class TempNode(template.Node): |
|
def __init__(self, func, template_, args, kwargs): |
|
self.func = func |
|
self.template = get_template(template_) |
|
self.args = [template.Variable(arg) for arg in args] |
|
self.kwargs = dict([(k, template.Variable(v)) for (k,v) in kwargs.items()]) |
|
|
|
def render(self, context): |
|
args = [context['request']] + [arg.resolve(context) for arg in self.args] |
|
kwargs = dict([ |
|
(key, val.resolve(context)) for (key, val) in self.kwargs.items() |
|
]) |
|
context.update(self.func(*args, **kwargs)) |
|
res = self.template.render(context) |
|
context.pop() |
|
return res |