Micro-framework out of Django#

Single file Django#

You don’t need microframeworks to build small APIs, because Django is a microframework itself. With the only difference: it scales!

Run result

$ curl http://127.0.0.1:8000/api/user/ -X POST -d '{"email": "djangomodernrest@wemake.services"}' -H 'Content-Type: application/json'
{"email":"djangomodernrest@wemake.services","uid":"b2655eac-4691-460b-9847-77f1319008a9"}

OpenAPI Schema

Preview openapi.json
{
  "components": {
    "schemas": {
      "ErrorDetail": {
        "description": "Base schema for error details description.",
        "properties": {
          "loc": {
            "items": {
              "anyOf": [
                {
                  "type": "integer"
                },
                {
                  "type": "string"
                }
              ]
            },
            "title": "Loc",
            "type": "array"
          },
          "msg": {
            "title": "Msg",
            "type": "string"
          },
          "type": {
            "title": "Type",
            "type": "string"
          }
        },
        "required": [
          "msg"
        ],
        "title": "ErrorDetail",
        "type": "object"
      },
      "ErrorModel": {
        "description": "Default error response schema.\n\nCan be customized.\nSee :ref:`customizing-error-messages` for more details.",
        "properties": {
          "detail": {
            "items": {
              "$ref": "#/components/schemas/ErrorDetail"
            },
            "title": "Detail",
            "type": "array"
          }
        },
        "required": [
          "detail"
        ],
        "title": "ErrorModel",
        "type": "object"
      },
      "UserCreateModel": {
        "properties": {
          "email": {
            "title": "Email",
            "type": "string"
          }
        },
        "required": [
          "email"
        ],
        "title": "UserCreateModel",
        "type": "object"
      },
      "UserResponseModel": {
        "properties": {
          "email": {
            "title": "Email",
            "type": "string"
          },
          "uid": {
            "format": "uuid",
            "title": "Uid",
            "type": "string"
          }
        },
        "required": [
          "email",
          "uid"
        ],
        "title": "UserResponseModel",
        "type": "object"
      }
    }
  },
  "info": {
    "title": "Django Modern Rest",
    "version": "0.1.0"
  },
  "openapi": "3.2.0",
  "paths": {
    "/api/user/": {
      "post": {
        "operationId": "postUserControllerApiUser",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/UserCreateModel"
              }
            }
          },
          "required": true
        },
        "responses": {
          "201": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/UserResponseModel"
                }
              }
            },
            "description": "Created"
          },
          "400": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Raised when request components cannot be parsed"
          },
          "406": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Raised when provided `Accept` header cannot be satisfied"
          },
          "422": {
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorModel"
                }
              }
            },
            "description": "Raised when returned response does not match the response schema"
          }
        }
      }
    }
  }
}

Microframeworks#

The single file example above is already a complete microframework app. But if you are reaching for one of the popular microframework styles, django-modern-rest drops into both without any special glue:

µDjango is a demo of exactly this idea: a whole Django app in a single file, exposed as a plain ASGIHandler and served by any ASGI server.

It is not a package you install, so there is nothing to integrate with. It is a shape your own file can take, and django-modern-rest fits into it without any glue code:

Run result

$ curl http://127.0.0.1:8000/user/ -X POST -d '{"email": "djangomodernrest@wemake.services"}' -H 'Content-Type: application/json'
{"email":"djangomodernrest@wemake.services","uid":"dc8029ef-19d8-43d3-b0a0-98fd186231ae"}

Run it with any ASGI server:

uvicorn udjango_style_asgi:app --reload

Note

µDjango itself is explicitly a demonstration project and is not meant for production. The pattern it shows, however, is just regular Django.

Scaling it for real projects#

However, all projects tend to grow while they are alive. Microframeworks handle the scale poorly, because they are not designed for this task.

We recommend using https://github.com/wemake-services/wemake-django-template to set up production ready Django boilerplate code with all the best practices.

It can handle any scale!