Django-Flex
A flexible query language for Django — let your frontend dynamically construct database queries
Your first API in 5 minutes. No serializers. No viewsets. Just config.
Features
- Field Selection — Request only the fields you need, including nested relations
- JSONField Support — Seamless dot notation for nested JSON data
- Dynamic Filtering — Full Django ORM operator support with composable AND/OR/NOT
- Smart Pagination — Limit/offset with cursor-based continuation
- Built-in Security — Row-level, field-level, and operation-level permissions
- Automatic Optimization — N+1 prevention with smart
select_related - Django-Native — Feels like a natural extension of Django
Installation
pip install django-flex
Quick Start
1. Add to Django
# settings.py
INSTALLED_APPS = ['django_flex', ...]
MIDDLEWARE = ['django_flex.middleware.FlexMiddleware', ...]
DJANGO_FLEX = {
'EXPOSE': {
# Role-first structure: role -> model -> config
'staff': {
'booking': {
'fields': ['id', 'status', 'customer.name', 'scheduled_date'],
'ops': ['get', 'list', 'add', 'edit', 'delete'],
},
},
},
}
2. Add URL
# urls.py
urlpatterns = [
path('api/', include('django_flex.urls')),
]
Done. Your API is live at /api/bookings/.
CRUD Operations
List
fetch('/api/bookings/');
{
"results": {
"1": {
"id": 1,
"status": "confirmed"
},
"2": {
"id": 2,
"status": "pending"
}
}
}
Get
fetch('/api/bookings/1');
{
"id": 1,
"status": "confirmed",
"customer": {
"name": "Aisha Khan"
}
}
Create
fetch('/api/bookings/', {
method: 'POST',
body: JSON.stringify({
customer_id: 1,
status: 'pending',
}),
});
{
"id": 3,
"status": "pending",
"customer_id": 1
}
Update
fetch('/api/bookings/1', {
method: 'PUT',
body: JSON.stringify({
status: 'completed',
}),
});
{
"id": 1,
"status": "completed"
}
Delete
fetch('/api/bookings/1', { method: 'DELETE' });
{
"deleted": true
}
Advanced Querying
All query options are sent in the request body.
Field Selection
fetch('/api/bookings/', {
method: 'GET',
body: JSON.stringify({
fields: 'id, status, customer.name',
}),
});
{
"results": {
"1": {
"id": 1,
"status": "confirmed",
"customer": {
"name": "Aisha Khan"
}
}
}
}
Nested Relations
{
fields: 'id, customer.name, customer.address.city';
}
{
"results": {
"1": {
"id": 1,
"customer": {
"name": "Aisha Khan",
"address": {
"city": "Sydney"
}
}
}
}
}
Wildcard Fields
{
fields: '*, customer.*';
}
Filtering — Exact Match
{
filters: {
status: 'confirmed';
}
}
{
"results": {
"1": {
"id": 1,
"status": "confirmed"
}
}
}
Filtering — Comparison
{
filters: {
'price.gte': 50,
'price.lte': 200
}
}
Filtering — Text Search
{
filters: {
'name.icontains': 'khan'
}
}
Filtering — List Membership
{
filters: {
'status.in': ['pending', 'confirmed']
}
}
Filtering — Null Check
{
filters: {
'assignee.isnull': true
}
}
Filtering — Date Range
{
filters: {
'created_at.gte': '2024-01-01',
'created_at.lte': '2024-12-31'
}
}
Filtering — Related Fields
{
filters: {
'customer.vip': true,
'customer.address.city': 'Sydney'
}
}
Filtering — OR Conditions
{
filters: {
or: {
status: 'pending',
urgent: true
}
}
}
Filtering — NOT Conditions
{
filters: {
not: {
status: 'cancelled';
}
}
}
Ordering
{
order_by: '-scheduled_date';
}
{
"results": {
"3": {
"scheduled_date": "2024-03-15"
},
"1": {
"scheduled_date": "2024-03-10"
}
}
}
Pagination
{
limit: 20,
offset: 0
}
{
"results": {},
"pagination": {
"offset": 0,
"limit": 20,
"has_more": true,
"next": {}
}
}
Why Django-Flex?
| Feature | Django-Flex | GraphQL | REST |
|---|---|---|---|
| Learning curve | Low (Django-native) | High | Low |
| Field selection | ✅ | ✅ | ❌ (fixed endpoints) |
| Dynamic filtering | ✅ | ✅ | Limited |
| Built-in security | ✅ | Manual | Manual |
| Django integration | Native | Requires graphene | Native |
| Schema definition | Optional | Required | N/A |
| N+1 prevention | Automatic | Manual | Manual |
Learn More
License
MIT
Metadata
Release files for django-flex 26.2.9
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | Actions |
|---|---|---|---|---|
| django_flex-26.2.9.tar.gz | 39.0 kB | Without provenance | Details for django_flex-26.2.9.tar.gz |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| django_flex-26.2.9-py3-none-any.whl | Python 3 | none | any | Details for django_flex-26.2.9-py3-none-any.whl |
Total release size: 79.9 kB
Release files / django_flex-26.2.9.tar.gz
| Download URL | django_flex-26.2.9.tar.gz |
|---|---|
| Size | 39.0 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
cc225b174e79dcf4990bdd84106cc16b59b6d39c79c593e157172f494f2abdb4
|
|
BLAKE2b-256 checksum How to use checksums |
01ae6252ca234f7f90085c6884d04648ef29bc7979d857d638a3cc1c61b0a74b
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.14.3
|
Release files / django_flex-26.2.9-py3-none-any.whl
| Download URL | django_flex-26.2.9-py3-none-any.whl |
|---|---|
| Size | 40.9 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
1a0a8d61c38fc89e2fdb61139ea8d08f1d74b53c3d727b4df599c4a91bc65869
|
|
BLAKE2b-256 checksum How to use checksums |
d0d0337358582605b69253d59923e8c046a16c774f5246d988b94198b6a9c7c8
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.14.3
|
Security for django-flex 26.2.9
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.