Skip to main content

A tiny, flexible framework layer on top of Django REST Framework.

Project description

humanoid_django

humanoid_django is a tiny framework layer on top of Django REST Framework. It is made for developers who want DRF power but do not want to repeat the same serializer, viewset, router, pagination, search, filtering, ordering, and role permission code in every project.

Goals

  • Create CRUD APIs in 3–4 lines.
  • Keep normal DRF available when you need full control.
  • Work with any model and any user-role style.
  • Support simple constants from roles.py like SUPER_ADMIN, ADMIN, USER.
  • Be easy for beginners, but flexible enough for real projects.

Installation

pip install humanoid_django

For local development from this folder:

python -m pip install -e .

Add apps in settings.py:

INSTALLED_APPS = [
    # ...
    "rest_framework",
    "humanoid_django",
]

Optional, for filters() support:

pip install "humanoid_django[filters]"
INSTALLED_APPS = [
    # ...
    "django_filters",
]

The easiest possible API

api.py

from humanoid_django import HumanoidAPI
from .models import Product

api = HumanoidAPI()
api.resource("products", Product)

urlpatterns = api.urls

Main project urls.py:

from django.urls import include, path
from products.api import urlpatterns as product_api

urlpatterns = [
    path("api/", include(product_api)),
]

Now you get these endpoints automatically:

GET     /api/products/
POST    /api/products/
GET     /api/products/{id}/
PUT     /api/products/{id}/
PATCH   /api/products/{id}/
DELETE  /api/products/{id}/

Example with roles.py

roles.py

SUPER_ADMIN = "SUPER_ADMIN"
ADMIN = "ADMIN"
USER = "USER"

api.py

from humanoid_django import HumanoidAPI
from .models import Product
from .roles import SUPER_ADMIN, ADMIN, USER

api = HumanoidAPI()

api.resource("products", Product).fields("id", "name", "price", "created_at").roles(
    default=[ADMIN, SUPER_ADMIN],
    list=[USER, ADMIN, SUPER_ADMIN],
    retrieve=[USER, ADMIN, SUPER_ADMIN],
    create=[ADMIN, SUPER_ADMIN],
    update=[ADMIN, SUPER_ADMIN],
    partial_update=[ADMIN, SUPER_ADMIN],
    destroy=[SUPER_ADMIN],
)

urlpatterns = api.urls

That means:

  • USER, ADMIN, and SUPER_ADMIN can list and retrieve products.
  • ADMIN and SUPER_ADMIN can create/update products.
  • Only SUPER_ADMIN can delete products.

Search, filter, order, optimize

api.resource("products", Product) \
    .fields("id", "name", "price", "category", "created_at") \
    .search("name", "category__name") \
    .filters("category", "is_active") \
    .ordering("name", "price", "created_at", default=["-created_at"]) \
    .optimize(select=["category"])

Then your API supports:

/api/products/?search=laptop
/api/products/?category=1
/api/products/?ordering=-price
/api/products/?fields=id,name,price
/api/products/?omit=created_at

Owner-based APIs

For models with a user, owner, created_by, or custom owner field:

api.resource("orders", Order).owner("user").roles(USER, owner=True)

This can restrict the queryset to the logged-in user and also allow object-level owner permission checks.

Use normal DRF whenever needed

You can still write a normal serializer:

from rest_framework import serializers
from .models import Product

class ProductSerializer(serializers.ModelSerializer):
    class Meta:
        model = Product
        fields = ["id", "name", "price"]

Then use it inside Humanoid:

api.resource("products", Product).serializer(ProductSerializer)

You can also write a normal ViewSet by extending HumanoidModelViewSet:

from humanoid_django import HumanoidModelViewSet
from humanoid_django.permissions import allow
from .models import Product
from .roles import ADMIN

class ProductViewSet(HumanoidModelViewSet):
    model = Product
    fields = ("id", "name", "price")
    permission_classes = [allow.roles(ADMIN)]

Permission helpers

from humanoid_django.permissions import allow

permission_classes = [allow.roles(ADMIN, SUPER_ADMIN)]
permission_classes = [allow.owner_or_roles(ADMIN, owner_field="created_by")]
permission_classes = [allow.action_roles({"list": [USER], "destroy": [SUPER_ADMIN]})]

By default, humanoid_django looks for roles in:

  • user.role
  • user.roles
  • user.user_type
  • user.type
  • Django groups, using group names as roles

You can customize that in settings.py:

HUMANOID_DJANGO = {
    "ROLE_FIELDS": ("role", "account_type"),
    "ROLE_NAME_FIELDS": ("name", "code", "slug", "value"),
    "GROUPS_AS_ROLES": True,
    "SUPERUSER_ALWAYS_ALLOWED": True,
    "STAFF_ALWAYS_ALLOWED": False,
    "DEFAULT_PAGE_SIZE": 20,
    "MAX_PAGE_SIZE": 200,
}

Response envelope, optional

By default, Humanoid keeps DRF responses normal. If you want all generated APIs to return {data, message, errors}, enable:

HUMANOID_DJANGO = {
    "ENVELOPE_RESPONSES": True,
}

REST_FRAMEWORK = {
    "EXCEPTION_HANDLER": "humanoid_django.exceptions.humanoid_exception_handler",
}

Scaffold starter files

python manage.py humanoid_start products

This creates:

  • products/api.py
  • products/roles.py

Build and upload to PyPI

python -m pip install --upgrade build twine
python -m build
python -m twine check dist/*
python -m twine upload dist/*

Compatibility

The package metadata targets:

  • Python 3.10+
  • Django 5.2+
  • Django 6.x
  • Django REST Framework 3.15+

Philosophy

Humanoid does not replace DRF. It removes repetitive code from common projects, then lets you drop back into normal DRF whenever you need custom behavior.

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

humanoid_django-0.1.0.tar.gz (16.4 kB view details)

Uploaded Source

Built Distribution

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

humanoid_django-0.1.0-py3-none-any.whl (17.9 kB view details)

Uploaded Python 3

File details

Details for the file humanoid_django-0.1.0.tar.gz.

File metadata

  • Download URL: humanoid_django-0.1.0.tar.gz
  • Upload date:
  • Size: 16.4 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.3

File hashes

Hashes for humanoid_django-0.1.0.tar.gz
Algorithm Hash digest
SHA256 800a658117ebbafd173587d0d40faabde5ce4b1b6c86c286c6bf20e92744a57d
MD5 a5709a7ff59639f47039cef3213b7e12
BLAKE2b-256 78be113c5acd541c3374ac0b84e2c90678f848cd152b19bfb7871b8492cc6df0

See more details on using hashes here.

File details

Details for the file humanoid_django-0.1.0-py3-none-any.whl.

File metadata

File hashes

Hashes for humanoid_django-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 9a359563aa5c25bb94d9d9f9bfab22e1d36942efcfa4b9197e882dd4233b6cd7
MD5 b5f7500206e0b28befeb67cd86c93dba
BLAKE2b-256 d7682927c9368e6df966fb42fc4ee8c62772308052eb0663365b58621787977e

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