Skip to main content

A powerful Django toolkit for rapid development — auth, caching, logging, serializers, and more.

Project description

Django Swifty

A powerful, lightweight Django toolkit that enhances your development experience with authentication, caching, structured logging, dynamic serializers, and expression evaluation — all with zero platform-specific dependencies.

Installation

pip install django-swifty

With Redis caching support:

pip install django-swifty[redis]

With all optional features:

pip install django-swifty[all]

Quick Start

Add swifty to your INSTALLED_APPS:

INSTALLED_APPS = [
    ...
    "swifty",
]

Features

🔐 Authentication & Authorization

JWT-based authentication with layered permissions via Django REST Framework.

from swifty.auth.permissions import SwiftyPermission
from swifty.viewsets.viewsets import SwiftyViewSet

class AdminPermission(SwiftyPermission):
    """Only allow users with admin or superuser role."""
    permission_layers = [
        {"path": "role", "allowed": ["admin", "superuser"]},
    ]

class MyViewSet(SwiftyViewSet):
    permission_classes = (AdminPermission,)

    def list(self, request):
        return Response({"items": []})

Features:

  • JWT token rotation and validation via AccessTokenManager
  • Layer-based permission checks with dynamic callables
  • Per-action permission and authentication class overrides

⚡ Caching

Method-level caching with pluggable backends (Redis by default).

from swifty.cache.manager import cache, cache_property

class ProductService:
    redis_cache_pattern = {"prefix": "PRODUCTS", "ttl": 3600, "vary_by": ["user_id"]}

    @cache(ttl=1800, static_key="featured")
    def get_featured(self):
        return Product.objects.filter(featured=True)

    @cache_property
    def categories(self):
        return Category.objects.all()

Features:

  • @cache decorator for methods with TTL, static keys, and vary-by
  • @cache_property for cached properties
  • Configurable cache backend via settings.CACHE_BACKEND
  • Auto-reconnection on Redis failures
  • Pipeline-based batch cache deletion

Configuration:

# settings.py
import redis

REDIS_CONNECTION_POOL = {
    "pool_1": redis.ConnectionPool(host="localhost", port=6379, db=1),
}

# Optional: custom cache backend
# CACHE_BACKEND = "myapp.cache.MyCustomCache"

📝 Structured Logging

Structured logging via structlog with automatic request context binding.

from swifty.logging.logger import SwiftyLoggerMixin

class OrderService(SwiftyLoggerMixin):
    def create_order(self, data):
        self.logger.info("Creating order", item_count=len(data["items"]))
        # ... business logic ...
        self.logger.info("Order created", order_id=order.id)

Features:

  • SwiftyLoggerMixin provides a cached self.logger property
  • Automatic module.ClassName logger naming
  • Request context binding (user, path, method) via RequestContext
  • JSON, console, and key-value formatters

Configuration:

# settings.py
# Swifty auto-configures logging if LOGGING is not set.
# Customize via:
SWIFTY_LOGGING_CONFIG = {
    "log_level": logging.DEBUG,
}

# Custom context fields:
CONTEXT_FIELDS_MAPPING = (
    ("user.username", "username"),
    ("user.id", "user_id"),
    ("method", "method"),
    ("path", "path"),
)

🔄 Dynamic Serializers

Build serializers dynamically from configuration with expression-based calculators and validators.

from swifty.serializers.manager import create_dynamic_serializer

fields_config = [
    {"field_name": "name", "type": "CharField", "required": True, "max_length": 100},
    {"field_name": "price", "type": "FloatField", "min_value": 0},
    {"field_name": "quantity", "type": "IntegerField", "default": 1},
    {
        "field_name": "total",
        "type": "FloatField",
        "calculator": {"expression": "price * quantity"},
    },
]

MySerializer = create_dynamic_serializer(fields_config)

Available field types: CharField, EmailField, URLField, UUIDField, IntegerField, FloatField, DecimalField, BooleanField, DateField, DateTimeField, DateRangeField, TimeField, DurationField, ListField, DictField, ChoiceField, MultipleChoiceField, SlugField, FileField, ImageField, JSONField, ReadOnlyField, HiddenField, SectionField, SectionManyField


🧮 Expression Evaluator

Safe mathematical and logical expression evaluation with AST-based security.

from swifty.expressionator.manager import ExpressionatorManager

em = ExpressionatorManager(data={"price": 100, "tax_rate": 0.1, "quantity": 3})

total = em.evaluate("price * quantity * (1 + tax_rate)")  # 330.0
is_bulk = em.evaluate("quantity > 5")  # False
discount = em.evaluate("max(price * 0.1, 10)")  # 10.0

Features:

  • AST node whitelisting for security (no arbitrary code execution)
  • Math functions (sin, cos, sqrt, pi, etc.)
  • Safe builtins (max, min, abs, len, sum, round, etc.)
  • Expression compilation caching for performance
  • Extensible via custom namespaces
from swifty.expressionator.namespace import ExpressionatorNamespace

class MyNamespace(ExpressionatorNamespace):
    def _expr_clamp(self, value, low, high):
        return max(low, min(high, value))

em = ExpressionatorManager(data={"x": 150}, namespace=MyNamespace)
em.evaluate("clamp(x, 0, 100)")  # 100

🛠 Utilities

Path-based data access:

from swifty.utils.mapper import getpath

data = {"user": {"profile": {"name": "Alice"}}}
getpath(data, "user.profile.name")  # "Alice"
getpath(data, "user.missing", "default")  # "default"

Dict-to-object conversion:

from swifty.utils.objects import DictObject

obj = DictObject({"user": {"name": "Alice", "tags": ["admin", "staff"]}})
obj.user.name  # "Alice"
obj.user.tags  # DotList(["admin", "staff"])

Once-trigger decorator:

from swifty.utils.decorators import once_trigger

class ExpensiveService:
    @property
    @once_trigger
    def connection(self):
        return create_expensive_connection()  # Called only once per instance

Dynamic module importing:

from swifty.utils.importer import import_module_attribute

MyClass = import_module_attribute("myapp.module.MyClass")

🌐 ViewSets

Enhanced DRF ViewSets with JWT auth, structured logging, and request context.

from swifty.viewsets.viewsets import SwiftyViewSet
from swifty.viewsets.exceptions import JsonException
from rest_framework.response import Response

class ProductViewSet(SwiftyViewSet):
    def list(self, request):
        self.logger.info("Listing products")
        return Response({"products": []})

    def create(self, request):
        if not request.data.get("name"):
            raise JsonException({"name": "This field is required."}, status_code=400)
        return Response({"created": True}, status=201)

Features:

  • Auto request context binding to logger
  • Per-action authentication and permission overrides
  • JsonException for structured JSON error responses
  • Double-initialization guard for request objects

Requirements

  • Python ≥ 3.10
  • Django ≥ 3.2
  • Django REST Framework ≥ 3.12

Configuration Reference

Setting Description Default
REDIS_CONNECTION_POOL Dict of Redis connection pools Required for Redis cache
CACHE_BACKEND Custom cache backend class path swifty.redis.cache.RedisCache
SWIFTY_LOGGING_CONFIG Kwargs for get_logging_config() {}
CONTEXT_FIELDS_MAPPING Request context field mappings See logging section

Contributing

We welcome contributions! Here's how you can help:

  1. Fork the repository
  2. Create your feature branch (git checkout -b feature/AmazingFeature)
  3. Commit your changes (git commit -m 'Add some AmazingFeature')
  4. Push to the branch (git push origin feature/AmazingFeature)
  5. Open a Pull Request

License

This project is licensed under the MIT License - see the LICENSE file for details.

Authors

  • Phuc Le - Initial work - Github

Made with ❤️ by the Django Swifty Team

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_swifty-2.0.0.tar.gz (29.8 kB view details)

Uploaded Source

Built Distribution

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

django_swifty-2.0.0-py3-none-any.whl (38.3 kB view details)

Uploaded Python 3

File details

Details for the file django_swifty-2.0.0.tar.gz.

File metadata

  • Download URL: django_swifty-2.0.0.tar.gz
  • Upload date:
  • Size: 29.8 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.14.3

File hashes

Hashes for django_swifty-2.0.0.tar.gz
Algorithm Hash digest
SHA256 f295b1802b65462dbe7de5f97988bbfdb76699cfc7fedeb0d7c2475f0d2ff386
MD5 b94c3761db4eca4d1718bd347552bbbb
BLAKE2b-256 650017e8f3012153c971a160e375b42c18d4c8e46cdf14d3a30b7a932da8e0c4

See more details on using hashes here.

File details

Details for the file django_swifty-2.0.0-py3-none-any.whl.

File metadata

  • Download URL: django_swifty-2.0.0-py3-none-any.whl
  • Upload date:
  • Size: 38.3 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.14.3

File hashes

Hashes for django_swifty-2.0.0-py3-none-any.whl
Algorithm Hash digest
SHA256 d6a2be9b492b734271f07fc468913378ad0baf93e5682233a4d1dda18168d54a
MD5 68fad3a534a7795bc5cd63e32f2b1d50
BLAKE2b-256 7896537d3015ce6c7e0209eb2a44a560dff5a9d8c2988c0c62f36947c8dda725

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