Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -231,7 +231,7 @@ def my_view(request):
## Decorator

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

```python
@jsonate_request
@jsonate_response
def my_view(request):
form = MyForm(request.POST)
if form.is_valid():
Expand Down
16 changes: 12 additions & 4 deletions jsonate/decorators.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import json
from jsonate.http import JsonateResponse
from django.http import HttpResponse

Expand All @@ -14,7 +15,7 @@ def inner(wrapper):
return wrapper
return inner

def jsonate_request(func):
def jsonate_response(func):
"""
Serializes whatever the view returns to JSON and returns it with
mimetype "application/json" (uses jsonate.http.JsonateResponse)
Expand All @@ -24,11 +25,11 @@ def jsonate_request(func):

examples:

@jsonate_request
@jsonate_response
def my_view(request):
return User.objects.all()

@jsonate_request
@jsonate_response
def my_view(request):
form = MyForm(request.POST or None)
if form.is_valid():
Expand All @@ -46,4 +47,11 @@ def wrapper(request, *args, **kwargs):
if request.GET.get("callback"):
return JsonateResponse(resp, jsonp_callback=request.GET['callback'])
return JsonateResponse(resp)
return wrapper
return wrapper


def deserialize_request(view_f):
"Deserialize a json request body to a Python object."
def _view_wrapper(request, *args, **kwargs):
return view_f(json.loads(request.body), *args, **kwargs)
return _view_wrapper
52 changes: 52 additions & 0 deletions jsonate/request_handler.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
from django.http import Http404
from django.core.exceptions import ValidationError


class APIReqHandler:
"""
The APIReqHandler class provides a wrapper that adds
a message parameter to a function that returns a dictionary.
Combine with the jsonate_response decorator to use with
clients expecting json.

If the view raised no errors, the message content is 'ok'.
Http404 and validation errors return the error message to the client,
all other exceptions are raised.

Example:
@jsonate_response
def my_view(request, some_arg)
return APIReqHandler(my_func).handle(some_arg)

Parameters:
- view_f (function): A function that returns a dictionary.
- resp_ok (function, optional): A function to execute if no errors are raised.
- resp_err (function, optional): A function to execute if errors are raised.

Methods:
- handle(*args, **kwargs) -- return the function with added message.
"""
def __init__(self, view_f, resp_ok=None, resp_err=None):
self.view_f = view_f
self.resp_ok = resp_ok or self._resp_ok
self.resp_err = resp_err or self._resp_error

@staticmethod
def _resp_ok(extra):
extra_data = extra or {}
return {
"message": "ok",
**{k: v for k, v in extra_data.items()}
}

@staticmethod
def _resp_error(err):
return {"message": f"{err.__class__.__name__}: {err}"}

def handle(self, *args, **kwargs):
try:
return self.resp_ok(self.view_f(*args, **kwargs))
except (Http404, ValidationError) as err:
return self.resp_err(err)
except Exception:
raise
4 changes: 2 additions & 2 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"

[project]
name = "jsonate"
version = "0.7.14"
version = "1.0.0"
authors = [
{name = "James Robert"},
{email = "jiaaro@gmail.com"}
Expand All @@ -14,7 +14,7 @@ license = {text = "MIT"}
keywords = ["django", "json", "templatetags"]
urls = {homepage = "http://jsonate.com"}
requires-python = ">=3.12"
dependencies = ["django>=4.2.6"]
dependencies = ["django>=5.1.0"]
readme = "README.md"
classifiers= [
"Development Status :: 4 - Beta",
Expand Down