Django API Server

Open-source Django API server that explains how to extend an existing codebase

This sample explains how to extend an existing Django API Starter and add another model managed via a new API node.

Codebase structure

PROJECT ROOT
β”œβ”€β”€ api                           # App containing all project-specific apps
β”‚   β”œβ”€β”€ apps.py
β”‚   β”œβ”€β”€ authentication            # Implements authentication app logic (register, login, session) logic
β”‚   β”‚   β”œβ”€β”€ apps.py
β”‚   β”‚   β”œβ”€β”€ backends.py           # Handles the active session authentication
β”‚   β”‚   β”œβ”€β”€ migrations
β”‚   β”‚   β”œβ”€β”€ serializers
β”‚   β”‚   β”‚   β”œβ”€β”€ login.py          # Handles the proccess of login for an user
β”‚   β”‚   β”‚   └── register.py       # Handle the creation of a new user
β”‚   β”‚   β”œβ”€β”€ tests.py              # Test for login, registration and session
β”‚   β”‚   └── viewsets       
β”‚   β”‚       β”œβ”€β”€ active_session.py # Handles session check
β”‚   β”‚       β”œβ”€β”€ login.py          # Handles login
β”‚   β”‚       β”œβ”€β”€ logout.py         # Handles logout
β”‚   β”‚       └── register.py       # Handles registration
|   |
β”‚   β”œβ”€β”€ fixtures                  # Package containg the project fixtures
β”‚   β”œβ”€β”€ __init__.py
β”‚   β”œβ”€β”€ routers.py                # Define api routes
β”‚   └── user                      # Implements user app logic
β”‚       β”œβ”€β”€ apps.py
β”‚       β”œβ”€β”€ __init__.py
β”‚       β”œβ”€β”€ migrations
β”‚       β”œβ”€β”€ serializers.py       # Handle the serialization of user object
β”‚       └── viewsets.py          # Handles  the modification of an user
|
β”œβ”€β”€ core                         # Implements app logic      
β”‚   β”œβ”€β”€ asgi.py
β”‚   β”œβ”€β”€ __init__.py
β”‚   β”œβ”€β”€ settings.py              # Django app bootstrapper
β”‚   β”œβ”€β”€ test_runner.py           # Custom  test runner
β”‚   β”œβ”€β”€ urls.py    
β”‚   └── wsgi.py
|
β”œβ”€β”€ docker-compose.yml
β”œβ”€β”€ Dockerfile
β”œβ”€β”€ .env                         # Inject Configuration via Environment
β”œβ”€β”€ manage.py                    # Starts the app
└── requirements.txt             # Contains development packages

Used Patterns

Working with Django Rest Framework, the most common design pattern is the Template Method Pattern.

It mostly consists of providing base/skeleton for some features with the possibility to override/extends these skeletons.

For example, you can check the code in api/user/viewsets.py. The UserViewSet inherits of viewsets.GenericsViewSet and CreateModelMixin and UpdateModelMixin.

The UpdateModelMixin provides the logic to update an object using PUT.

We only need to rewrite the method which handles the updating and provides the serializer_class and the permission_classes.

How to use the API

POSTMAN usage

The API is actually built around these endpoints :

  • api/users/signup

  • api/users/login

  • api/users/edit

  • api/users/checkSession

  • api/users/logout

Register - api/users/register

Response :

Login - api/users/login

Once it's done, rewrite the apps.py file with the following content.

Response :

Logout - api/users/logout

Response :

cURL usage

Let's edit information about the user and check a session using cURL.

Check Session- api/users/checkSession

Response :

Edit User - api/users/edit

Response :

How to extend API

Add a new model - transactions

To add a model for transaction in the project, let's create a new application in the api directory.

  • Creating the app using django-admin command in the api directory.

  • Then modify the name and the label of the app in apps.py

  • And add the app in the INSTALLED_APPS in the settings.py of the project.

Then modify the apps.py file.

And don't forget to add the default_app_config in the __init__.py file the transaction directory.

We can now register the application in settings.py file.

Add API interface to manage transactions

Creating an API interface to manage transactions usually go this way :

  • Creating the model

  • Creating the serializer

  • Write the views or the viewsets

  • Register the viewsets by creating routes

We've already created the model for transaction.

Let's create the serializer.

A serializer allows us to convert complex Django complex data structures such as querysets or model instances in Python native objects that can be easily converted JSON/XML format, but a serializer also serializes JSON/XML to naive Python.

And now the viewsets.

The routes for the transaction interface API should look like this :

  • api/transactions/create -> create transaction

  • api/transactions/edit/id-> edit transaction

  • api/transactions/delete/id -> delete transaction

  • api/transactions/get/id -> get specific transaction

  • api/transactions/get -> get all transactions

The ViewSet class comes with built-in actions :

  • list

  • retrieve

  • create

  • update

  • partial_update

  • destroy

And to make sure the names of the URLs match what we need, we'll be using actions.

First of all, create a file name viewsets in the transactions directory.

And add the following code.

Then let's rewrite the get_queryset method. This method is used by the viewset to return a list of objects, here a list of transactions.

Great. Now, let's make sure DRF will exactly match the URLs we want. First of all, we have to block the default routes.

And we can write our own actions now.

Let's start with api/transactions/create.

To avoid name collision with the default built-in method create , we are naming the method create_transaction. Hopefully, DRF provides the option to specify the url_path of the method.

Let's write the actions for api/transactions/get and api/transactions/get/id

Notice that for the get/id (get_transaction), we are writing the url_path using regex expression.

And finally, the actions for api/transactions/delete/id and api/transactions/edit.

Now, we can register the viewset.

There is already a routers.py file which contains the routes for api/users.

Let's create a different router for transactions.

In the api directory, create a new package called routers. Move the file routers.py in it and rename it to users.py.

Then create a new file named transactions.py and add the following code to register TransactionViewSet actions.

And the last step, open the urls.py file in the core directory and add the transaction router.

And that's it. You can start testing the API with Postman.

Congratulations. You just learned :

  • How to add a new model;

  • How to add a serializer for this model;

  • How to rewrite viewset behavior and actions to match your needs.

Last updated

Was this helpful?