# -*- coding: utf-8 -*- from functools import wraps from inspect import getargspec from django.http import HttpResponse from django.utils.simplejson import loads as json_decode, dumps as json_encode from django.utils.functional import curry from django.conf import settings from django.shortcuts import render_to_response from django.template import RequestContext, generic_tag_compiler, Node from django.template import TemplateSyntaxError, Variable from common.util import stringify_keys from django.db import transaction class AjaxError(Exception): pass def json_decode_fallback(value): try: return json_decode(value) except ValueError: return value def ajax(login_required=False, method=None, encode_result=True): def decorator(fun): @wraps(fun) def ajax_view(request): kwargs = {} request_params = None if method == 'post': request_params = request.POST elif method == 'get': request_params = request.GET fun_params, xx, fun_kwargs, xxxx = getargspec(fun) if request_params: request_params = dict((key, json_decode_fallback(value)) for key, value in request_params.iteritems() if fun_kwargs or key in fun_params) kwargs.update(stringify_keys(request_params)) res = None if login_required and not request.user.is_authenticated(): res = {'result': 'logout'} if not res: try: res = fun(request, **kwargs) except AjaxError as e: res = {'result': e.args[0]} transaction.rollback() if encode_result: if 'result' not in res: res['result'] = 'ok' return HttpResponse(json_encode(res), mimetype='application/json') else: return res return ajax_view return decorator def render(template=None, mimetype=None): mimetype = mimetype or settings.DEFAULT_CONTENT_TYPE template1 = template def decorator(func): template = template1 # no cóż... if not template: template = func.__name__ + '.html' @wraps(func) def renderer(request, *args, **kw): output = func(request, *args, **kw) if isinstance(output, (list, tuple)): return render_to_response(output[1], output[0], RequestContext(request), mimetype=mimetype) elif isinstance(output, dict): return render_to_response(template, output, RequestContext(request), mimetype=mimetype) return output return renderer return decorator def simple_tag(register, takes_context=False): def decorator(func): params, xx, xxx, defaults = getargspec(func) if takes_context: if params[0] == 'context': params = params[1:] else: raise TemplateSyntaxError("Any tag function decorated with takes_context=True must have a first argument of 'context'") class SimpleNode(Node): def __init__(self, vars_to_resolve): self.vars_to_resolve = map(Variable, vars_to_resolve) def render(self, context): resolved_vars = [var.resolve(context) for var in self.vars_to_resolve] if takes_context: args = [context] + resolved_vars else: args = resolved_vars try: return func(*args) except Exception as e: raise return type(e).__name__+': '+str(e) compile_func = curry(generic_tag_compiler, params, defaults, getattr(func, "_decorated_function", func).__name__, SimpleNode) compile_func.__doc__ = func.__doc__ register.tag(getattr(func, "_decorated_function", func).__name__, compile_func) return func return decorator