Skip to content
API v2

icon picker
API v2


The goal of this refactor is to have a clean and lean API that can then share with the public and third-parties.
This change should also enable us switch between different python frameworks and also move to microservices where/when the need be.


0. Framework

We would be sticking with due to its stability and its robust permission management features.

1. Basic folder structure

Screenshot 2021-02-15 at 15.49.53.png
To ensure that we still have the current API working whilst developing v2, we’d create a v2 sub folder - in each app - where most of the work would be done. The file would maintain its current location in the app’s package.
Views would be a module that would contain different view files for each package. e.g for the fund app, there’s are a lot of views so we’d break them down in such a way that we can have similar views in a file. Then in the __init__py file of the views module, we import all views. For smaller apps e.g badges We can have just a single file.
We would be making use of viewsets with list and detail routes as opposed to APIView. This would help to generate the documentation via would be explained later.

from rest_framework import viewsets

class UserViewSet(viewsets.ViewSet):
def create(self, request, **kwargs):

def update(self, request, pk=None, **kwargs):

def retrieve(self, request, pk=None, **kwargs):

def list(self, request, **kwargs):
def destroy(self, request, pk=None, **kwargs):
def register_2fa(self, request, **kwargs):
def activate_user(self, request, **kwargs):
Tests would be in their own package where we can have unit tests (services, models) and integration tests (views)
There would be a Service class in file which would contain code that bridges view-model interaction so the view does not interact with the models directly but via the service class. For example,
in plans/ there would exist a PlanService class . When a call is made to the create plan endpioint, we pass the data to the PlanService to create the plan and then get a response. i.e
from import PlanService
from rest_framework import viewsets

class PlanViewSet(viewsets.ViewSet):

def create(self, request, **kwargs):
code ommited for brevity
plans_service = PlanService(**args)
result = plan_service.create_plan(**args)
If the PlanService has to interact with models from the card app, it would be done via the CardService *(We may need to consider using DI here) would contain the serializers of the models in their respective app. The serializers would handle validation for things like data type checking, text length check etc. We can have a number of serializers per model. e.g we can have a UserSerializer for update and retrieve and a UserCreationSerializer for create. would contain app specific background tasks (via celery) would contain the router for the package. We would then import the router url in the project level would contain specific functions that are re-used in the app services. We would rarely have to create this file as most of the work would be done by the Services already. We would most likely use the project level utils file for shared utility code used in multiple services.

2. Documentation.*

Another advantage of using Django Rest Framework is the vast amount of libraries one has available to work with.
. Core API allows us to create a documentation page for our APIs that frontend developers can easily interact with. Here is an example of what it looks like -
It requires little configuration as drf is able to read metadata from serializers and use the model structure create the documentation. It is also customizable.

3. Permissions.

We would be handling permission with DRF’s default permission handler. We’d create custom permission classes for different types of users, we would also be considering creating permissions on an app basis e.g
ReadPlanPermission,ReadCardPermission,UpdatePlanPermission , etc


Everyone on the team understands DRF
We would be working with the documentation created on

Want to print your doc?
This is not the way.
Try clicking the ⋯ next to your doc name or using a keyboard shortcut (
) instead.