Skip to content

Django

A whole Django project in one file. In your project, the view goes in an app and the URL pattern in its urls.py.

import sys

from django.conf import settings
from django.http import HttpRequest, HttpResponse
from django.urls import path
from django.views.decorators.csrf import csrf_exempt

from jsonrpcserver import Result, Success, dispatch, method

# A whole Django project in one file. In a real project, the view and the URL
# pattern go in your app as usual.
settings.configure(
    ROOT_URLCONF=__name__,
    ALLOWED_HOSTS=["localhost", "127.0.0.1"],
    SECRET_KEY="replace-me",
    # Bigger requests get 400 Bad Request. Django's default is 2.5 MB.
    DATA_UPLOAD_MAX_MEMORY_SIZE=1_000_000,
)


@method
def ping() -> Result:
    return Success("pong")


@csrf_exempt
def jsonrpc(request: HttpRequest) -> HttpResponse:
    # max_batch_size: see the Security page.
    if response := dispatch(request.body.decode(), max_batch_size=100):
        return HttpResponse(response, content_type="application/json")
    return HttpResponse(status=204)


urlpatterns = [path("", jsonrpc)]

if __name__ == "__main__":
    from django.core.management import execute_from_command_line

    execute_from_command_line(
        [sys.argv[0], "runserver", "localhost:8000", "--noreload"]
    )

Django refuses a body bigger than DATA_UPLOAD_MAX_MEMORY_SIZE with 400 Bad Request when the view reads request.body. The default is 2.5 MB, and the example sets it explicitly. max_batch_size limits how many requests one batch can hold. See Security.

The view is exempt from CSRF checks, because JSON-RPC clients don't send a CSRF token. Use another way to authenticate them, such as a token in a header. To give methods request.user, pass it in the context. Context has an example.

runserver is Django's development server. For production, use a WSGI or ASGI server, as the Django docs describe.

Try it

Save the example as django_server.py, install Django (pip install django), and run it:

python django_server.py

Then send it a request from another terminal:

curl -s -H 'Content-Type: application/json' -d '{"jsonrpc": "2.0", "method": "ping", "id": 1}' http://localhost:8000/
Output
{"jsonrpc": "2.0", "result": "pong", "id": 1}

The jsonrpcclient quickstart sends the same request from Python.