[](https://crates.io/crates/pyforge-django)
[](https://pypi.org/project/pyforge-django)
[](LICENSE-MIT)
[](https://www.python.org)
[](https://www.djangoproject.com)
[](https://github.com/abdulwahed-sweden/pyforge/actions)
# PyForge
Rust-accelerated serialization and validation for Django — drop-in, zero rewrite.
## What Is PyForge
PyForge moves Django REST Framework's serialization and validation hot paths
from Python to Rust. It reads your existing Django model definitions, compiles
a typed schema once at startup, and processes field values through Rust-native
code on every request. The result is 3-8x faster API responses for list views,
bulk operations, and any endpoint that touches more than a handful of records.
It is designed for Django developers running production APIs on DRF who need
better throughput without migrating to a different framework.
## Benchmarks
Measured on CPython 3.12, Rust 1.93, macOS ARM64.
Model: 9-field `RentalApplication` (CharField, DecimalField, DateTimeField, UUIDField, etc.)
| Serialize 100 records | 1.5-2.5 ms | 340 µs | **3-5x** |
| Serialize 1,000 records | 15-25 ms | 3.4 ms | **4-6x** |
| Serialize 10,000 records | 150-250 ms | 40.4 ms | **4-6x** |
| Validate 1,000 fields | 2-4 ms | 321 µs | **5-8x** |
| Validate 10,000 fields (parallel) | 20-40 ms | ~3 ms | **6-10x** |
Small batches (<10 records) show minimal gain due to the Python/Rust bridge overhead (~5-8µs per call).
Full methodology and per-field-type breakdown: [BENCHMARKS.md](BENCHMARKS.md)
## Installation
```bash
pip install pyforge-django
```
Add the app to your Django settings:
```python
INSTALLED_APPS = [
...
"django_pyforge",
]
```
## Quickstart
```python
from django_pyforge import ModelSchema, serialize_instance, validate_instance
from django_pyforge.serializers import RustSerializerMixin
from rest_framework import serializers
# 1. Compile a schema once (e.g., in AppConfig.ready)
schema = ModelSchema(RentalApplication)
# 2. Serialize a single instance — one Rust call, all fields
result = serialize_instance(instance, schema)
# 3. Validate an instance against the schema
report = validate_instance(instance, schema)
if not report["is_valid"]:
print(report["errors"])
# 4. Or use the DRF mixin — zero changes to your existing code
class ApplicationSerializer(RustSerializerMixin, serializers.ModelSerializer):
class Meta:
model = RentalApplication
fields = "__all__"
```
## Supported Django Field Types
| CharField | `String` | max_length enforced in characters, not bytes |
| TextField | `String` | No length limit |
| IntegerField | `i32` | Full range |
| BigIntegerField | `i64` | Full range |
| DecimalField | `rust_decimal::Decimal` | Full precision preserved — never converted to float |
| DateField | `chrono::NaiveDate` | ISO 8601 format |
| DateTimeField | `chrono::DateTime<Utc>` | RFC 3339 with timezone (USE_TZ=True) |
| TimeField | `chrono::NaiveTime` | ISO 8601 format |
| UUIDField | `uuid::Uuid` | Hyphenated and non-hyphenated accepted |
| BooleanField | `bool` | Serialized as True/False, never as 1/0 |
| FloatField | `f64` | NaN and Infinity rejected at serialization |
| JSONField | `serde_json::Value` | Full nested structure preserved |
| BinaryField | `Vec<u8>` | Base64 encoded for JSON transport |
| EmailField | `String` | max_length enforced |
| URLField | `String` | max_length enforced |
| SlugField | `String` | Character set validated |
## Requirements
- **Python** 3.11 or newer
- **Django** 4.2 LTS or 5.x
- **Rust** 1.75+ (only needed when building from source)
- **Platforms:** Linux, macOS, Windows (manylinux wheels published to PyPI)
## Architecture
PyForge has three layers. `ModelSchema` is a Rust `#[pyclass]` that reads
Django's `_meta` API once and compiles field descriptors into a cached struct.
`serialize_instance` takes a Django model object and the cached schema, extracts
every field value via `getattr` in a single Rust call, converts each to a native
Rust type (Decimal, DateTime, UUID, etc.), serializes to JSON-compatible output,
and returns a Python dict. `RustSerializerMixin` sits on top as a DRF mixin that
automatically classifies which fields are simple model fields (Rust-accelerated)
and which are computed fields (delegated back to DRF). For validation batches
above 64 fields, Rayon distributes work across CPU cores while the GIL is released.
## Crates
| [`pyforge`](https://crates.io/crates/pyforge) | Core Rust-Python binding library |
| [`pyforge-django`](https://crates.io/crates/pyforge-django) | Django integration layer |
| `pyforge-ffi` | CPython C API bindings |
| `pyforge-macros` | Procedural macros |
| `pyforge-build-config` | Build-time Python detection |
## License
MIT — [Abdulwahed Mansour](https://github.com/abdulwahed-sweden)