1
votes

I have recently inherited an API built with Django and DRF. I need to add some endpoints to the API but have never worked with Django or DRF before so I am trying to come up to speed as quickly as possible.

I am wondering how to do custom endpoints that don't just translate data too/from the backend database. A for instance might be an endpoint that reads data from the DB then compiles a report and returns it to the caller in JSON. But I suppose that right now the simplest method would be one that when the endpoint is hit just prints 'Hello World' to the log and returns a blank page.

I apologize if this seems basic. I've been reading through the docs and so far all I can see is stuff about serializers when what I really need is to be able to call a custom block of code.

Thanks.

2
You need to read the DRF docs first and get familiar with the methods they provide. You can easily achieve what you need. You simply do it without DRF. Do your calculations and at the end return JsonResponse and provide it with your dictionary of results. docs.djangoproject.com/en/3.0/ref/request-response/…Navid Zarepak
If you want to interact in a DRF, json'esque way, then you can look at DRF's APIViewRoss Rogers

2 Answers

4
votes

if you want your REST endpoint to have all: GET, POST, PUT, DELETE etc. functionality then you have to register a route in your urls.py:

urls.py:

from rest_framework import routers
from django.urls import path, include
from . import views

router = routers.DefaultRouter()
router.register(r'hello', views.HelloWorldViewSet)

urlpatterns = [
    # Wire up our API using automatic URL routing.
    # rest_framework api routing
    path('api/', include(router.urls)),
    # This requires login for put/update while allowing get (read-only) for everyone.
    path('api-auth/', include('rest_framework.urls', namespace='rest_framework'))
]

now the url: /hello/ points to the HelloWorldViewSet.

in your views.py add the HelloWorldViewSet that will inherits from the rest_framework.viewsets.ViewSet class. You can override the ViewSet default class behavior by defining the following "actions": list(), create(), retrieve(), update(), partial_update(), destroy(). For displaying "hello world" on GET you only need to override list():

so in your views.py:

from rest_framework import viewsets
from rest_framework.response import Response

class HelloWorldViewSet(viewsets.ViewSet):
    def list(self, response):
        return Response('Hello World')

So, in your more advanced list() function you have to interact with the database, to retrieve the data you want, process it and create the report as a json serializable dictionary and return it as a Response object.

If you don't want to override the standard list action, you could instead add a new action to the HelloWorldViewSet let's call it report:

so in your views.py:

from rest_framework import viewsets
from rest_framework.response import Response
from rest_framework.decorators import action

class HelloWorldViewSet(viewsets.ViewSet):
    @action(detail=False)
    def report(self, request, **kwargs):
        return Response('Hello World')

I hope this is what you were looking for.

Note that you don't need django-rest-framework if you are not interested in POST, PUT, PATCH, DELETE, etc... you can simply add a path to your urls.py that points to a Django view function that returns a Django JsonResponse object containing your report.

1
votes

One good option for you would be DRF actions. Docs here

The action allows you to choose a relevant view for what you wanna do, so you can just pop things into the API you inherited. No additional setup needed, they show up next to the regular routes.