Skip to content

Commit 2b161aa

Browse files
authored
Merge pull request #32 from weswil07/add-and-rename-features-for-apis
Rename jsonate_request -> jsonate response. Add deserialize_request. Add APIReqHandler.
2 parents 7e1fd60 + ba39c50 commit 2b161aa

4 files changed

Lines changed: 68 additions & 8 deletions

File tree

README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -231,7 +231,7 @@ def my_view(request):
231231
## Decorator
232232

233233
The `JsonateResponse` is great, but life could get even easier! The
234-
`@jsonate_request` decorator (inspired by the ajax_request decorator
234+
`@jsonate_response` decorator (inspired by the ajax_request decorator
235235
in django-annoying) will try to serialize anything a view returns
236236
(via JsonateResponse) return it in an HttpResponse with mimetype
237237
"application/json"
@@ -241,7 +241,7 @@ The only thing it will *not* try to serialize is an HttpResponse.
241241
example:
242242

243243
```python
244-
@jsonate_request
244+
@jsonate_response
245245
def my_view(request):
246246
form = MyForm(request.POST)
247247
if form.is_valid():

jsonate/decorators.py

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import json
12
from jsonate.http import JsonateResponse
23
from django.http import HttpResponse
34

@@ -14,7 +15,7 @@ def inner(wrapper):
1415
return wrapper
1516
return inner
1617

17-
def jsonate_request(func):
18+
def jsonate_response(func):
1819
"""
1920
Serializes whatever the view returns to JSON and returns it with
2021
mimetype "application/json" (uses jsonate.http.JsonateResponse)
@@ -24,11 +25,11 @@ def jsonate_request(func):
2425
2526
examples:
2627
27-
@jsonate_request
28+
@jsonate_response
2829
def my_view(request):
2930
return User.objects.all()
3031
31-
@jsonate_request
32+
@jsonate_response
3233
def my_view(request):
3334
form = MyForm(request.POST or None)
3435
if form.is_valid():
@@ -46,4 +47,11 @@ def wrapper(request, *args, **kwargs):
4647
if request.GET.get("callback"):
4748
return JsonateResponse(resp, jsonp_callback=request.GET['callback'])
4849
return JsonateResponse(resp)
49-
return wrapper
50+
return wrapper
51+
52+
53+
def deserialize_request(view_f):
54+
"Deserialize a json request body to a Python object."
55+
def _view_wrapper(request, *args, **kwargs):
56+
return view_f(json.loads(request.body), *args, **kwargs)
57+
return _view_wrapper

jsonate/request_handler.py

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
from django.http import Http404
2+
from django.core.exceptions import ValidationError
3+
4+
5+
class APIReqHandler:
6+
"""
7+
The APIReqHandler class provides a wrapper that adds
8+
a message parameter to a function that returns a dictionary.
9+
Combine with the jsonate_response decorator to use with
10+
clients expecting json.
11+
12+
If the view raised no errors, the message content is 'ok'.
13+
Http404 and validation errors return the error message to the client,
14+
all other exceptions are raised.
15+
16+
Example:
17+
@jsonate_response
18+
def my_view(request, some_arg)
19+
return APIReqHandler(my_func).handle(some_arg)
20+
21+
Parameters:
22+
- view_f (function): A function that returns a dictionary.
23+
- resp_ok (function, optional): A function to execute if no errors are raised.
24+
- resp_err (function, optional): A function to execute if errors are raised.
25+
26+
Methods:
27+
- handle(*args, **kwargs) -- return the function with added message.
28+
"""
29+
def __init__(self, view_f, resp_ok=None, resp_err=None):
30+
self.view_f = view_f
31+
self.resp_ok = resp_ok or self._resp_ok
32+
self.resp_err = resp_err or self._resp_error
33+
34+
@staticmethod
35+
def _resp_ok(extra):
36+
extra_data = extra or {}
37+
return {
38+
"message": "ok",
39+
**{k: v for k, v in extra_data.items()}
40+
}
41+
42+
@staticmethod
43+
def _resp_error(err):
44+
return {"message": f"{err.__class__.__name__}: {err}"}
45+
46+
def handle(self, *args, **kwargs):
47+
try:
48+
return self.resp_ok(self.view_f(*args, **kwargs))
49+
except (Http404, ValidationError) as err:
50+
return self.resp_err(err)
51+
except Exception:
52+
raise

pyproject.toml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
44

55
[project]
66
name = "jsonate"
7-
version = "0.7.14"
7+
version = "1.0.0"
88
authors = [
99
{name = "James Robert"},
1010
{email = "jiaaro@gmail.com"}
@@ -14,7 +14,7 @@ license = {text = "MIT"}
1414
keywords = ["django", "json", "templatetags"]
1515
urls = {homepage = "http://jsonate.com"}
1616
requires-python = ">=3.12"
17-
dependencies = ["django>=4.2.6"]
17+
dependencies = ["django>=5.1.0"]
1818
readme = "README.md"
1919
classifiers= [
2020
"Development Status :: 4 - Beta",

0 commit comments

Comments
 (0)