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:
@cachedecorator for methods with TTL, static keys, and vary-by@cache_propertyfor 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:
SwiftyLoggerMixinprovides a cachedself.loggerproperty- Automatic
module.ClassNamelogger 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
JsonExceptionfor 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:
- Fork the repository
- Create your feature branch (
git checkout -b feature/AmazingFeature) - Commit your changes (
git commit -m 'Add some AmazingFeature') - Push to the branch (
git push origin feature/AmazingFeature) - 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
Metadata
Release files for django-swifty 2.0.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| django_swifty-2.0.0.tar.gz | 29.8 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| django_swifty-2.0.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 68.2 kB
Release files / django_swifty-2.0.0.tar.gz
| Download URL | django_swifty-2.0.0.tar.gz |
|---|---|
| Size | 29.8 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
f295b1802b65462dbe7de5f97988bbfdb76699cfc7fedeb0d7c2475f0d2ff386
|
|
BLAKE2b-256 checksum How to use checksums |
650017e8f3012153c971a160e375b42c18d4c8e46cdf14d3a30b7a932da8e0c4
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.14.3
|
Release files / django_swifty-2.0.0-py3-none-any.whl
| Download URL | django_swifty-2.0.0-py3-none-any.whl |
|---|---|
| Size | 38.3 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
d6a2be9b492b734271f07fc468913378ad0baf93e5682233a4d1dda18168d54a
|
|
BLAKE2b-256 checksum How to use checksums |
7896537d3015ce6c7e0209eb2a44a560dff5a9d8c2988c0c62f36947c8dda725
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.14.3
|