decorators.py
3.2 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
# -*- coding: utf-8 -*-
from functools import wraps
from inspect import getargspec
from django.http import HttpResponse, Http404
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, defaults = getargspec(fun)
if defaults:
required_params = fun_params[1:-len(defaults)]
else:
required_params = fun_params[1:]
if set(required_params) - set(request_params):
raise Http404
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), content_type='application/json')
else:
return res
return ajax_view
return decorator
# żeby były linki do szablonów w PyCharm przy ajaxach
render_ajax = ajax
def render(template=None, content_type=None):
content_type = content_type or settings.DEFAULT_CONTENT_TYPE
def decorator(func):
template_name = template or 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),
content_type=content_type)
elif isinstance(output, dict):
return render_to_response(
template_name, output, RequestContext(request),
content_type=content_type)
return output
return renderer
return decorator