Howto call remote method without Django model – Django rest framework tip

Hi everyone,

I want to show my solution how to add support for remote calling procedure (method) into an existing RESTful API infrastructure.
I extend APIView and override POST method that is a key part of code. I called the new class surprisingly RunActionView.

# The APIView for calling custom methods

from jsonschema import validate
from rest_framework import status
from rest_framework.permissions import IsAuthenticated
from rest_framework.views import APIView
from rest_framework.response import Response

class RunActionView(APIView):
    permission_classes = (IsAuthenticated,)

    def post(self, request):
        data = request.data
        action = data.get("action", '')
        args = data.get("args", '')
        r_data = {}

        if action:
            try:
                r_data["result"] = getattr(self, action)(args)
                r_data["success"] = True
            except Exception as e:
                r_data["message"] = f"Action {action} failed.\n{e}"
                r_data["success"] = False
        else:
            r_data["message"] = f"No action set."
            r_data["success"] = False

        return Response(r_data, status=status.HTTP_200_OK)
    

    # the custom method
    def calc(self, args):

        schema = {
            "type": "object",
            "properties": {
                "arg1": {"type": "number"},
                "arg2": {"type": "number"},
            }
        }
        validate(args, schema)

        arg1 = args["arg1"]
        arg2 = args["arg2"]

        result = arg1 * arg2
        return result

Make sure to add our class RunActionView into file urls.py.

# the content of urls.py
urlpatterns += path('api/actions/', RunActionView.as_view()),

There is an example of calling the remote method “calc” with two parameters arg1 and arg2.

# the rest client example with the token authentication

url = 'https://127.0.0.1/api/tasks/'
# add your a super secret token here
token = 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx'
head = {'Authorization': f'Token {token}'}

data = {
    "action": "calc",
    "args": {"arg1": 11, "arg2": 22},
     }

response = requests.post(url, headers=head, json=data)
payload = response.json()

if not response.ok:
    raise Exception(f'POST {url} code:{r.status_code}\n{payload}')
else:
    print(payload)

I know that this approach is not perfect and that is not strict RESTfull and deserves some improvements.
My example can be useful as a basic scaffold for your final solutions.

That is all and as always, any improvement ideas are welcomed.

Enjoy!
Hanz