🚀
AppSeed Docs
  • AppSeed
  • Support
  • App Generator
  • Boilerplate Code
    • API Servers
      • API Unified Definition
      • API Server Django
      • API Server Flask
      • API Server Node JS
    • Boilerplate Django Dashboards
    • Boilerplate Django Apps
    • Boilerplate Flask Dashboards
    • Boilerplate Flask Apps
    • Boilerplate Jinja
    • Django Templates
      • Django Template Volt
      • Django Argon Dashboard
      • Django Material Dashboard
  • Developer Tools
    • Django API Generator
    • Django Dynamic API
    • Django Dynamic DataTables
    • Flask Dynamic API
    • Flask Dynamic DataTables
    • DB Introspection Tool
  • PRODUCTS
    • Full-stack
      • Full-Stack React Purity
      • Full-Stack React Material
      • Full-Stack React Datta Able
      • Full-Stack React Berry
    • React
      • React Node JS Berry
      • React Node JS Datta Able
      • React Node JS Datta PRO
      • React Node Material Kit PRO
      • React Firebase Datta Able
      • React Firebase Datta PRO
      • Django React Datta Able
      • Django React Datta PRO
      • Flask React Datta Able
    • Flask Apps
      • Flask Material Kit
      • Flask Material Kit PRO
      • Flask Material Kit 2 PRO
      • Flask Pixel Lite
      • Flask Pixel PRO
      • Flask Soft Design
      • Flask Soft Design PRO
    • Flask Dashboards
      • Flask Adminator
      • Flask AdminLTE
      • Flask Azia Dashboard
      • Flask Argon Dashboard
      • Flask Argon PRO
      • Flask Atlantis Dark
      • Flask Atlantis Dark PRO
      • Flask Black Dashboard
      • Flask Black PRO
      • Flask CoreUI
      • Flask Datta Able
      • Flask Datta Able PRO
      • Flask Datta Able ENH
      • Flask Gradient Able
      • Flask Light Bootstrap
      • Flask Light Blue
      • Flask Material Dashboard
      • Flask Material PRO
      • Flask MaterialPro Lite
      • Flask MaterialPRO
      • Flask Material Admin
      • Flask Star Admin
      • Flask Soft Dashboard
      • Flask Soft Dashboard Pro
      • Flask Shards Dashboard
      • Flask SB Admin
      • Flask Sleek Admin
      • Flask Volt
      • Flask Volt PRO
      • Flask Tabler
    • Django Apps
      • Django Pixel Lite
      • Django Pixel PRO
      • Django Material Kit
      • Django Material Kit PRO
      • Django Material Kit 2 PRO
      • Django Soft Design
      • Django Soft Design PRO
    • Django Dashboards
      • Django Adminator
      • Django AdminLTE
      • Django Azia Dashboard
      • Django Argon Dashboard
      • Django Argon PRO
      • Django Atlantis Dark
      • Django Atlantis Dark PRO
      • Django Black Dashboard
      • Django Black PRO
      • Django CoreUI
      • Django Datta Able
      • Django Datta Able PRO
      • Django Datta Able ENH
      • Django Gradient Able
      • Django Light Bootstrap
      • Django Light Blue
      • Django Material Dashboard
      • Django Material PRO
      • Django MaterialPro Lite
      • Django MaterialPro
      • Django Star Admin
      • Django Soft Dashboard
      • Django Soft Dashboard PRO
      • Django Soft Dashboard ENH
      • Django Shards Dashboard
      • Django SB Admin
      • Django Volt
      • Django Volt PRO
      • Django Tabler
    • Eleventy 11ty
      • Soft UI Design
    • Jinja Templates
      • Jinja Argon Dashboard
      • Jinja AdminLTE
      • Jinja Atlantis Lite
      • Jinja Black Dashboard
      • Jinja Datta Able PRO
      • Jinja Dashkit v3
      • Jinja Light Bootstrap
      • Jinja Material Dashboard
      • Jinja Now UI Dashboard
      • Jinja Paper Dashboard
      • Jinja Pixel Lite
      • Jinja Pixel PRO
      • Jinja SB Admin
      • Jinja Volt Bootstrap 5
      • Jinja Volt PRO
  • Features
    • Flask
      • Extended User Model
  • Free Samples
    • Django Samples
      • Django Create Model
      • Django User Profile
      • Django Sales Charts
      • Django Routing Sample
      • Django API Server
  • Technologies
    • Django
      • Getting Started
      • Django v4 Release
    • FastAPI
      • Getting Started
    • Flask
      • Getting Started
      • Flask v2.0 Release
    • MySql
      • Install MySql on Windows
      • Install MySql on Ubuntu
    • Material UI
      • Getting Started
    • Next JS
      • Getting Started
      • Sample Next.js Project
      • Deploy a Next.js application on Netlify
      • Best Practices for NextJS projects
    • Python
      • Getting Started
    • Supabase
      • Getting Started
  • Deployment
    • Google Cloud Platform
      • Deploy Django on GCP
    • App Platform by DO
      • App Platform - Deploy Django
    • AWS - Amazon Services
      • Deploy Django on AWS
    • Render Deployment Platform
      • Deploy Flask to Render
      • Deploy Django to Render
      • Deploy React to Render
      • Deploy Django & React to Render
  • Content
    • What IS
      • What IS Apache
      • What IS Bulma
      • What IS Boilerplate Code
      • What IS CentOS
      • What IS Django
      • What IS Eleventy
      • What IS Flask
      • What IS Gunicorn
      • What IS Heroku
      • What IS JAMStack
      • What IS Jinja
      • What IS Nginx
      • What IS Panini
      • What IS Pipenv
      • What IS Python
      • What IS React
      • What IS Static Site
      • What IS Svelte
      • What IS Ubuntu
      • What IS uWsgi
      • What IS WSGI
      • Two-Tier Architecture
      • Single-Tier Architecture
      • N-Tier Architecture
    • Getting Started
      • Getting Started with Django
      • Django Templates
      • Getting Started with Flask
      • Getting Started with Next JS
    • How To
      • OAUth - Get Github Secrets
      • OAUth - Get Twitter Secrets
      • Crawl Website in Python
      • Setup CentOS for coding
      • Setup Ubuntu for coding
      • Setup Windows for coding
      • Install Pyhton
      • Install Pyhton 3.8 on Ubuntu
      • Install WSL
      • Install Docker on Windows
      • Getting Started with Python
      • Django Customize Admin UI
      • Django Chart Example
      • Django - Add Debug Toolbar
      • Django MySql Database
      • Django Dockerizing App
      • Django Reset Password
      • Django Extend User Model
      • Django Integrate DRF Library
      • Django Data Tables
      • Django Simple Charts
      • Django Social Login
      • Django Stripe Payments
      • Django HEROKU Deployment
      • Django AWS Deployment
      • Django Google Cloud Deploy
      • Django Azure Deployment
      • Install Flask
      • Code a simple app In Flask
      • Structure a Flask project
      • Flask Dockerizing App
      • Flask Reset Password
      • Flask User Profile
      • Flask Integrate Flask-RestX
      • Flask Data Tables
      • Flask Simple Charts
      • Flask Social Login
      • Flask Stripe Payments
      • Flask Deploy on Apache
      • Flask Deploy on HEROKU
      • Flask AWS Deployment
      • Flask Google Cloud Deploy
      • Flask Azure Deployment
      • How to Implement JWT Authentication in React
    • Tutorials
      • Django - How to Install
      • Django For Beginners
      • Django Request Object
      • Django Forms
      • Django Auth System
      • Flask - Code a simple App
      • Minimal Programming Kit
      • Parse HTML Components
    • Programming Languages
      • Php
      • Python
    • Frameworks
      • Django
      • Flask
    • Design Systems
      • Argon Design System
      • Soft UI Design System
    • Partners
      • BootstrapDash Agency
      • Creative-Tim Agency
      • CodedThemes Agency
      • CoreUI Agency
      • Themesberg Agency
      • WrapPixel Agency
    • Bootstrap Templates
      • Adminator
      • AdminKit
      • AdminLTE
      • Azia Dashboard PRO
      • Atlantis Lite Template
      • Atlantis PRO Template
      • Argon Dashboard Template
      • Argon Dashboard PRO
      • Black Dashboard Template
      • Black Dashboard PRO
      • CoreUI Template
      • Datta Able Template
      • Datta Able PRO Template
      • Light Bootstrap Template
      • Light Bootstrap PRO
      • Material Dashboard Template
      • Material Dashboard PRO
      • Material UI Kit
      • MaterialPro Lite
      • MaterialPro Wpx
      • Now UI Dashboard
      • Now UI Dashboard PRO
      • Paper Dashboard
      • Paper Dashboard PRO
      • Pixel Lite Template
      • Pixel PRO
      • Star Admin Template
      • Soft UI Dashboard
      • Soft UI Dashboard PRO
      • Shards Dashboard
      • Volt Dashboard Template
      • Volt Dashboard Pro Template
      • Tabler Template
    • Bulma CSS Templates
      • Dashkit PRO
      • Dashkit PRO v3
    • React Templates
      • Berry React Dashboard
      • CoreUI React
    • Vue Templates
      • Vuetify Material Dashboard
    • How to Fix
      • Cannot import name 'TextField' from 'wtforms'
      • ImportError: cannot import name 'safe_str_cmp' from 'werkzeug.security'
Powered by GitBook
On this page
  • Codebase structure
  • Used Patterns
  • How to use the API
  • How to extend API

Was this helpful?

  1. Free Samples
  2. Django Samples

Django API Server

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

PreviousDjango Routing SampleNextDjango

Last updated 2 years ago

Was this helpful?

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

  • - original project

  • - the source code with new enhancements

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

POST api/users/register
Content-Type: application/json

{
    "username":"test",
    "password":"pass", 
    "email":"test@appseed.us"
}

Response :

{
    "success": true,
    "userID": 1,
    "msg": "The user was successfully registered"
}

Login - api/users/login

cd api && django-admin startapp transactions

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

POST /api/users/login
Content-Type: application/json

{
    "password":"pass", 
    "email":"test@appseed.us"
}

Response :

{
    "success": true,
    "token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpZCI6MSwiZXhwIjoxNjI4NzgxNTY4fQ.mB_YcZxZJd37r_4NYnLYeCByEHKGBC2ob0xe9KgcOII",
    "user": {
        "_id": 1,
        "username": "test",
        "email": "test@appseed.us"
    }
}

Logout - api/users/logout

POST api/users/logout
Content-Type: application/json
authorization: JWT_TOKEN (returned by Login request)

{
    "token":"JWT_TOKEN"
}

Response :

{
    "success": true,
    "msg": "Token revoked"
}

cURL usage

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

Check Session- api/users/checkSession

curl --request POST \
  --url http://127.0.0.1:8000/api/users/checkSession \
  --header 'Authorization: eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpZCI6MSwiZXhwIjoxNjI4NzgxNTY4fQ.mB_YcZxZJd37r_4NYnLYeCByEHKGBC2ob0xe9KgcOII' \
  --header 'Content-Type: application/json'

Response :

{
  "success": true
}

Edit User - api/users/edit

curl --request POST \
  --url http://127.0.0.1:8000/api/users/edit \
  --header 'Authorization: eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpZCI6MSwiZXhwIjoxNjI4NzgxNTY4fQ.mB_YcZxZJd37r_4NYnLYeCByEHKGBC2ob0xe9KgcOII' \
  --header 'Content-Type: application/json' \
  --data '{
	"username": "tester",
	"email": "test@admin.us",
	"userID": 1
}'

Response :

{
  "success": true
}

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.

cd api && django-admin startapp transaction

Then modify the apps.py file.

# api/transaction/apps.py

from django.apps import AppConfig


class TransactionConfig(AppConfig):
    default_auto_field = 'django.db.models.BigAutoField'
    name = 'api.transaction'
    label = 'api_transaction'

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

# api/transaction/__init__.py

default_app_config = "api.transaction.apps.TransactionConfig"

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

# core/settings.py

INSTALLED_APPS = [
    ...
    "api.authentication",
    "api.transaction"
]

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.

# api/transaction/serializers.py

from api.transaction.models import Transaction
from rest_framework import serializers


class TransactionSerializer(serializers.ModelSerializer):
    info = serializers.CharField(allow_null=True, allow_blank=True)
    price = serializers.IntegerField(required=True)

    class Meta:
        model = Transaction
        fields = ["id", "product", "price", "qty", "discount", "info"]
        read_only_field = ["id", "created"]

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

  • list

  • retrieve

  • create

  • update

  • partial_update

  • destroy

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

And add the following code.

# api/transactions/viewsets.py

from rest_framework import viewsets, status
from rest_framework.response import Response
from rest_framework.exceptions import ValidationError, NotFound, MethodNotAllowed
from rest_framework.decorators import action
from rest_framework.permissions import IsAuthenticated

from django.core.exceptions import ObjectDoesNotExist

from api.transaction.models import Transaction
from api.transaction.serializers import TransactionSerializer


class TransactionViewSet(viewsets.ModelViewSet):
    serializer_class = TransactionSerializer
    permission_classes = (IsAuthenticated,)
    http_method_names = ['get', 'post']
    
    not_found_message = {"success": False, "msg": "This object doesn't exist."}
    missing_id_message = {"success": False, "msg": "Provide a transaction id."}

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.

class TransactionViewSet(viewsets.ModelViewSet):
    ...

    def get_queryset(self):
        return Transaction.objects.all()

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

class TransactionViewSet(viewsets.ModelViewSet):
    ...

    def list(self, request, *args, **kwargs):
        raise MethodNotAllowed('GET')

    def create(self, request, *args, **kwargs):
        raise MethodNotAllowed('POST')

    def destroy(self, request, *args, **kwargs):
        raise MethodNotAllowed('DELETE')

    def update(self, request, *args, **kwargs):
        raise MethodNotAllowed('PUT')

    def retrieve(self, request, *args, **kwargs):
        raise MethodNotAllowed('GET')

And we can write our own actions now.

Let's start with api/transactions/create.

class TransactionViewSet(viewsets.ModelViewSet):
    ...

    @action(methods=['post'], detail=False, url_path='create')
    def create_transaction(self, request, *args, **kwargs):
        data = request.data

        serializer = self.serializer_class(data=data)
        serializer.is_valid(raise_exception=True)
        serializer.save()

        return Response({
            "success": True
        }, status.HTTP_201_CREATED)

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

class TransactionViewSet(viewsets.ModelViewSet):
    ...
    
    @action(methods=['get'], detail=False, url_path='get')
    def get_transactions(self, request, *args, **kwargs):

        transactions = self.get_queryset()

        page = self.paginate_queryset(transactions)

        if page is not None:
            serializer = self.get_serializer(page, many=True, context=self.get_serializer_context())
            return self.get_paginated_response(serializer.data)

        serializer = self.get_serializer(transactions, many=True, context=self.get_serializer_context())
        return Response({
            "success": True,
            "transactions": serializer.data
        }, status=status.HTTP_200_OK)

    @action(methods=['get'], detail=False, url_path=r'get/(?P<transaction_id>\w+)')
    
    def get_transaction(self, request, transaction_id=None, *args, **kwargs):

        if transaction_id is None:
            raise ValidationError(self.missing_id_message)

        try:
            obj = Transaction.objects.get(pk=transaction_id)
        except ObjectDoesNotExist:
            raise NotFound(self.not_found_message)

        serializer = self.get_serializer(obj)

        return Response({
            "success": True,
            "transaction": serializer.data
        }, status=status.HTTP_200_OK)

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.

class TransactionViewSet(viewsets.ModelViewSet):
    ...
    @action(methods=['post'], detail=False, url_path=r'edit/(?P<transaction_id>\w+)')
    def edit_transaction(self, request, transaction_id=None, *args, **kwargs):

        if transaction_id is None:
            raise ValidationError(self.missing_id_message)

        try:
            obj = Transaction.objects.get(pk=transaction_id)
        except ObjectDoesNotExist:
            raise NotFound(self.not_found_message)

        serializer = self.get_serializer(obj, data=request.data, partial=True)
        serializer.is_valid(raise_exception=True)
        self.perform_update(serializer)

        if getattr(obj, "_prefetched_objects_cache", None):
            obj._prefetched_objects_cache = {}

        return Response({
            "success": True
        }, status.HTTP_200_OK)

    @action(methods=['post'], detail=False, url_path=r'delete/(?P<transaction_id>\w+)')
    def delete_transaction(self, request, transaction_id=None, *args, **kwargs):

        if transaction_id is None:
            raise ValidationError(self.missing_id_message)

        try:
            obj = Transaction.objects.get(pk=transaction_id)
        except ObjectDoesNotExist:
            raise NotFound(self.not_found_message)

        obj.delete()

        return Response({
            "success": True
        }, status.HTTP_200_OK)

Now, we can register the viewset.

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

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.

# api/routers/transactions.py

from rest_framework import routers

from api.transaction.viewsets import TransactionViewSet

router = routers.SimpleRouter(trailing_slash=False)

router.register('', TransactionViewSet, basename='transactions')

urlpatterns = [
    *router.urls,
]

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

# core/urls.py

from django.urls import path, include

urlpatterns = [
    path("api/users/", include(("api.routers.users", "api-users"), namespace="api-users")),
    path("api/transactions/", include(("api.routers.transactions", "api-transactions"), namespace="api-transactions"))
]

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.

Let's create the .

A 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 .

The class comes with built-in :

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

Let's create a different for transactions.

Django API Server
Django API Server Sample
serializer
serializer
viewsets
ViewSet
actions
actions
router