decorators.py 2.56 KB
# -*- coding: utf-8 -*-

from functools import wraps
from inspect import getargspec

from django.http import HttpResponse
from django.template.loader import render_to_string
from django.conf import settings
from django.shortcuts import render_to_response
from django.template import RequestContext
from django.db import transaction

from common.util import json_decode, json_encode
from common.util import stringify_keys


class AjaxError(Exception):
  pass

def json_decode_fallback(value):
  try:
    return json_decode(value)
  except ValueError:
    return value

def ajax(login_required=True, method=None, encode_result=True, template=None):
  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:
          transaction.rollback()
          res = {'result': e.args[0]}
      if template:
        res = {'html': render_to_string(template, res, RequestContext(request))}
      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

# żeby były linki do szablonów w PyCharm przy ajaxach
def render_template(t):
  return lambda x: x