Skip to main content

Easy to use django package for building APIs quicker than ever, built on top of django-ninja-extra

Project description

Django SwiftAPI Documentation [Still Under Development]

Overview

Django SwiftAPI provides a powerful yet simple abstraction for automatically generating CRUD APIs, automatic schema generation and robust file handling — currently supporting both local storage and Amazon S3, built on top of django-ninja-extra. The core of this system is the use of:

  • SwiftBaseModel: A base model with built-in support for controlling request & responses, CRUD specifications, file fields, ownership, schema customization, object validations etc all out-of-the-box.
  • SwiftBaseModelController: A customizable controller that automates schema generations & CRUD operations. All you need to do is plug-in your SwiftBaseModel & it handles everything in the background.

This documentation explains how to use these components, configure your project, and extend the system for your needs.


Guide


Installation

Before you start working, you need some familiarity on django, django-ninja & django-ninja-extra with it's modelcontrolling capabilities.

Install it using:

pip install django_swiftapi

Then, add these in your INSTALLED_APPS:

INSTALLED_APPS = [
    ...,
    'ninja_extra',
    'django_swiftapi',
]

Database Recommendation

  • django_swiftapi heavily relies on the ArrayField for managing file-fields. So you need to use a database that supports ArrayField. Normally PostgreSQL is a good fit.

Model Definition

Inherit all your models from SwiftBaseModel to enable automatic shema generations, CRUD and file handling. Request & response schemas are also auto-generated based on specifications of this model.

Example:

from django.db import models
from django_swiftapi.modelcontrol.base_models import SwiftBaseModel
from django_swiftapi.crud_operation.files_handlers import Files_Param

class MyDocument(SwiftBaseModel):
    # You can use any django-specified fields here
    title = models.CharField(max_length=255)
    description = models.TextField(blank=True)
    
    # If you're storing files:
    # Example file field (ArrayField)
    file_field = ArrayField(models.CharField(max_length=200), default=list, size=5, blank=True, null=True)
    
    ## Required configuration for file handling
    files_fields = ['file_field', ]  # Put all your file-fields names here
    files_params_list = [
        # For each file-fields, specify configurations here
        Files_Param(
            field_name="file_field",
            access="public",  # or "private"
            storage="local",  # or "amazons3"
            file_size_limit=10,  # MB
            validate_images=True,
        ),
    ]
    
    # Customize field requirements
    required_to_create = ['title']
    required_to_update = []
    
    # Exclude fields from requests/responses
    exclude_in_request = ['id', 'created', 'updated', 'created_by']  # If you override this list, make sure add these mentioned here. It will prevent showing them in the request-schema.
    exclude_in_response = []
    
    # Optional: Ownership checking
    obj_owner_check_before_save = True
    obj_fields_to_check_owner = []

Model Options

Option Type Default Description
exclude_in_request list[str] ['id', 'created', 'updated', 'created_by'] Specified fields here are excluded from request schemas
exclude_in_response list[str] [] Specified fields here are excluded from response schemas
required_to_create list[str] [] Specified fields here are treated as 'required' while creating an object of this model
required_to_update list[str] [] Specified fields here are treated as 'required' while updating an object of this model
files_fields list[str] [] List of file field names, these fields will be considered as file-fields by django_swiftapi
files_params_list list[Files_Param] [] File configuration parameters for each file-field, this is required
obj_owner_check_before_save bool False Enable ownership validation before save. enabling will tell django_swiftapi to check if the requesting user is the user that created this object
obj_fields_to_check_owner list[str] [] A list of fields that link to other objects. Django SwiftAPI will use them to check if the user making the request created those related objects.
created_by_field str 'created_by' Field name for ownership tracking. you can modify it but default is recommended

Model-Controller Setup

Create modelcontrollers by inheriting from SwiftBaseModelController:

All Configurations:

from ninja_extra import api_controller, permissions
from django_swiftapi.modelcontrol.base_modelcontrollers import SwiftBaseModelController
from .models import MyDocument

@api_controller("/documents",)
class DocumentController(SwiftBaseModelController):

    model_to_control = MyDocument

    create_enabled: bool = False
    create_path: str = 'create'
    create_info: str = 'create an item'
    create_request_schemas: list[tuple[str, str, Schema, bool]] = None
    create_response_schemas: dict[int, Schema] = None
    create_custom_permissions_list: list = []
    create_premium_check: bool = False

    retrieve_one_enabled: bool = False
    retrieve_one_path: str = 'retrieveone/{id}'
    retrieve_one_info: str = 'retrieve an item'
    retrieve_one_depth = 0
    retrieve_one_response_schemas: dict[int, Schema] = None
    retrieve_one_custom_permissions_list: list = []
    retrieve_one_obj_permission_check: bool = False
    retrieve_one_premium_check: bool = False

    filter_enabled: bool = False
    filter_path: str = 'filter'
    filter_info: str = 'filter & get the listed result'
    filter_depth = 0
    filter_request_schemas: list[tuple[str, str, Schema, bool]] = None
    filter_response_schemas: dict[int, Schema] = None
    filter_custom_permissions_list: list = []
    filter_obj_permission_check: bool = False
    filter_premium_check: bool = False

    update_enabled: bool = False
    update_path: str = '{id}/update'
    update_info: str = 'update or add files to an item'
    update_request_schemas: list[tuple[str, str, Schema, bool]] = None
    update_response_schemas: dict[int, Schema] = None
    update_custom_permissions_list: list = []
    update_obj_permission_check: bool = False
    update_premium_check: bool = False

    file_retrieve_enabled: bool = False
    file_retrieve_path: str = '{id}/file/retrieve'
    file_retrieve_info: str = 'retrieve a single file of an item'
    file_retrieve_request_schemas: list[tuple[str, str, Schema, bool]] = None
    file_retrieve_response_schemas: dict[int, Schema] = None
    file_retrieve_custom_permissions_list: list = []
    file_retrieve_obj_permission_check: bool = False
    file_retrieve_premium_check: bool = False

    files_remove_enabled: bool = False
    files_remove_path: str = '{id}/files/remove'
    files_remove_info: str = 'remove files of an item', 
    files_remove_request_schemas: list[tuple[str, str, Schema, bool]] = None
    files_remove_response_schemas: dict[int, Schema] = None
    files_remove_custom_permissions_list: list = []
    files_remove_obj_permission_check: bool = False
    files_remove_premium_check: bool = False

    delete_enabled: bool = False
    delete_path: str = '{id}/delete'
    delete_info: str = 'delete an item with all its files'
    delete_response_schemas: dict[int, Schema] = None
    delete_custom_permissions_list: list = []
    delete_obj_permission_check: bool = False
    delete_premium_check: bool = False

Model-Controller Options

CRUD Operations

Option Type Default Description
create_enabled bool False Enable create endpoint
retrieve_one_enabled bool False Enable retrieve endpoint
filter_enabled bool False Enable filter/search endpoint
update_enabled bool False Enable update endpoint
delete_enabled bool False Enable delete endpoint

File Operations

Option Type Default Description
file_retrieve_enabled bool False Enable file retrieval endpoint
files_remove_enabled bool False Enable file removal endpoint

Permission Options

Option Type Default Description
*_custom_permissions_list list [] Custom permissions for specific operation
*_obj_permission_check bool False Check object ownership for operation

Path Customization (You can leave it to the default)

Option Type Default Description
create_path str 'create' Custom path for create endpoint
retrieve_one_path str 'retrieveone/{id}' Custom path for retrieve endpoint
filter_path str 'filter' Custom path for filter endpoint
update_path str '{id}/update' Custom path for update endpoint
delete_path str '{id}/delete' Custom path for delete endpoint
file_retrieve_path str '{id}/file/retrieve' Custom path for file retrieve
files_remove_path str '{id}/files/remove' Custom path for file removal

You can also customize their info and schemas. just set the variables properly.


URL Configuration

Configure your URLs to include the API endpoints (Reference):

# urls.py
from django.contrib import admin
from django.urls import path, include
from ninja_extra import NinjaExtraAPI
from your_app.controllers import DocumentController

api = NinjaExtraAPI()
api.register_controllers(DocumentController)

urlpatterns = [
    path('admin/', admin.site.urls),
    path('api/', api.urls),
]

urlpatterns += static(settings.STATIC_URL, document_root=settings.STATIC_ROOT)
urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)

That's it!


File Handling

File Configuration

Configure file handling using Files_Param:

from crud_operation.files_handlers import Files_Param

files_params_list = [
    Files_Param(
        field_name="name_of_your_field",    # Field name in model
        access="public",                    # "public" or "private"
        storage="local",                    # "local" or "amazons3"
        file_size_limit=10,                 # Size limit in MB
        validate_images=True,               # Validate image files
    ),
    Files_Param(
        field_name="name_of_your_field",
        access="private",
        storage="amazons3",
        file_size_limit=20,
        validate_images=False,
    ),
]

Then in settings.py (use what you need):

# local
PUBLIC_LOCAL_FILE_WRITE_LOCATION = "" # ex: 'dummy_site_files/public'
PUBLIC_LOCAL_FILE_URL_PREFIX = "" # ex: '/media'
PRIVATE_LOCAL_FILE_WRITE_LOCATION = "" # ex: 'dummy_site_files/private'

# amazon s3
PUBLIC_AMAZONS3_BUCKET_NAME = ""
PUBLIC_AMAZONS3_FILE_WRITE_LOCATION = ""
PUBLIC_AMAZONS3_FILE_URL_PREFIX = ""
PRIVATE_AMAZONS3_BUCKET_NAME = ""
PRIVATE_AMAZONS3_FILE_WRITE_LOCATION = ""

# Needed in both cases
MEDIA_ROOT = PUBLIC_LOCAL_FILE_WRITE_LOCATION
MEDIA_URL = '/media/'  # this value '/media/' is necessary for serving files during development

File Operations

The system automatically provides these file operations:

  • Upload: Files are uploaded during create/update operations
  • Retrieve: Download files via /file/retrieve endpoint
  • Remove: Delete specific files via /files/remove endpoint
  • Storage: Automatic handling of local and S3 storage

File Access Control

  • Public files: Accessible without authentication
  • Private files: Require authentication and ownership verification

Authentication & Permissions

django_swiftapi is highly compatible with django-allauth. So, if you're using django-allauth, you can validate authentications directly in your modelcontrollers.

Using Built-in Authentication Classes

from django_swiftapi.modelcontrol.authenticators import (
    djangoallauth_UserAuthentication,
    base_UserAuthentication
)

# Using allauth authentication
@api_controller("/api", permissions=[djangoallauth_UserAuthentication()])
class MyController(SwiftBaseModelController):
    pass

Customizing Authentication Class

If you're using any other user authentication system, you need to define your own authentication class overriding just one function:

# Create custom authentication
class CustomAuthentication(base_UserAuthentication):
    def has_permission(self, request, view):
        # Your custom logic for verifying if the user is authenticated
        # return the user object if authenticated else None

then use it like this:

@api_controller("/api", permissions=[CustomAuthentication()])
class MyController(SwiftBaseModelController):
    pass

Permission Levels

  1. Controller Level: Applied to all endpoints in the controller
  2. Operation Level: Specific permissions per CRUD operation
  3. Object Level: Ownership-based permissions

Ownership Checking

Enable object-level permissions:

class DocumentController(SwiftBaseModelController):
    retrieve_one_obj_permission_check = True  # Only owner can retrieve
    update_obj_permission_check = True        # Only owner can update
    delete_obj_permission_check = True        # Only owner can delete

Filtering and Search

The filter endpoint supports:

  • Field-based filtering
  • Search functionality via URL parameters
  • Pagination [Can be set according to django-ninja specs]
  • Custom filter expressions

Example filter request:

POST /api/documents/filter
{
    "title": "My Document",
    "created__gte": "2024-01-01"
}

You can basically use everything provided by django-ninja & django-ninja-extra!


Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

django_swiftapi-0.1.2.tar.gz (29.0 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

django_swiftapi-0.1.2-py3-none-any.whl (29.1 kB view details)

Uploaded Python 3

File details

Details for the file django_swiftapi-0.1.2.tar.gz.

File metadata

  • Download URL: django_swiftapi-0.1.2.tar.gz
  • Upload date:
  • Size: 29.0 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.11.5

File hashes

Hashes for django_swiftapi-0.1.2.tar.gz
Algorithm Hash digest
SHA256 f5c01da332f18c800a9c2cd7ce5e989dbf015f5a6feeed0d5f2615f23f11ad61
MD5 86f79b13349fba14a1c32fd461da824e
BLAKE2b-256 19da1769e7f7227a9b620ce75cb63506a8639cfa206a1415e64aa25ff260ceb0

See more details on using hashes here.

File details

Details for the file django_swiftapi-0.1.2-py3-none-any.whl.

File metadata

File hashes

Hashes for django_swiftapi-0.1.2-py3-none-any.whl
Algorithm Hash digest
SHA256 8281e55de3633d9ca334be0dc73757281258d682f7f0ee81352e240ece58ee79
MD5 0ccae83cdf4bdad447955334243bb8b3
BLAKE2b-256 51f3ab2287e25944a22a89a15d18cd18d9b527ac465d5de4b0af1d4e921a0594

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page