Dynamic query API for Django REST Framework
Project description
django-qlab
Dynamic query API and bundled React UI for Django REST Framework. Inspect model data, run filtered queries, save and replay them — no custom views required.
What ships
- Dynamic model querying with field selection and nested AND / OR / NOT filters
- Metadata endpoint — fields, types, relations, operators and autocomplete
- Neighborhood endpoint for relation exploration
- Bundled React + TypeScript UI served directly from
qlab.urls - Saved queries with create, update, delete and bulk operations
- Query run history with replay and save-from-history
- Per-user settings stored in the database
- Django admin integration for all persistence models
Install
pip install django-qlab
Add the required apps:
# settings.py
INSTALLED_APPS = [
...
"django.contrib.staticfiles",
"rest_framework",
"drf_spectacular",
"qlab",
]
Mount the URLs:
# urls.py
from django.urls import include, path
urlpatterns = [
...
path("qlab/", include("qlab.urls")),
]
Run migrations and collect static files:
python manage.py migrate
python manage.py collectstatic
Open /qlab/ in your browser — done.
Setup in 5 steps
pip install django-qlab- Add
qlab(and its dependencies) toINSTALLED_APPS - Include
qlab.urlsin your URL config python manage.py migrate && python manage.py collectstatic- Open
/qlab/
No separate frontend server. No npm. The compiled UI ships with the package.
Optional: login protection
Subclass QLabView to enforce authentication on the UI entrypoint:
# urls.py
from django.contrib.auth.mixins import LoginRequiredMixin
from django.urls import include, path
from qlab.views import QLabView
class SecuredQLabView(LoginRequiredMixin, QLabView):
login_url = "/admin/login/"
urlpatterns = [
path("qlab/", SecuredQLabView.as_view(), name="qlab"),
path("qlab/", include("qlab.urls")),
]
Optional: queryset scoping
Override QLabFrontendApiViewSet to scope queries per user, tenant or business group:
from rest_framework import permissions
from qlab.api_views import QLabFrontendApiViewSet
class ScopedQLabViewSet(QLabFrontendApiViewSet):
permission_classes = [permissions.IsAuthenticated]
def get_queryset(self, model):
return model.objects.filter(tenant=self.request.user.tenant)
Then mount the scoped ViewSet before the default qlab.urls include:
urlpatterns = [
path("qlab/", SecuredQLabView.as_view(), name="qlab"),
path("qlab/api/query/", ScopedQLabViewSet.as_view({"post": "post"}), name="qlab-query"),
path("qlab/", include("qlab.urls")),
]
Settings
Add a QLAB_SETTINGS dict to your Django settings to override defaults:
# settings.py
QLAB_SETTINGS = {
"DEFAULT_APP_LABEL": "myapp", # pre-select this app in the UI
"PAGE_SIZE": 100, # default page size
"MAX_PAGE_SIZE": 500, # hard cap per request
"MAX_RELATION_DEPTH": 2, # how deep relation graphs expand
"MAX_FILTER_CONDITIONS": 10, # max filter nodes per query
"MAX_NODES": 100, # max records returned by neighborhood
"ALLOWED_APPS": [], # restrict to specific app labels (empty = all)
"ENVIRONMENT_LABEL": "Production", # set qlab env
}
API surface
All routes are mounted relative to the prefix you chose (e.g. /qlab/):
| Method | Path | Description |
|---|---|---|
GET |
/ |
Bundled React UI |
GET |
/api/bootstrap/ |
Initial data load (models, settings) |
POST |
/api/query/ |
Run a filtered, paginated query |
POST |
/api/metadata/ |
Model field and relation schema |
POST |
/api/neighborhood/ |
Relation graph for a set of records |
GET / PATCH |
/api/settings/ |
Per-user UI settings |
GET / POST |
/api/saved-queries/ |
List and create saved queries |
GET / PATCH / DELETE |
/api/saved-queries/<id>/ |
Manage a single saved query |
POST |
/api/saved-queries/<id>/run/ |
Execute a saved query |
GET |
/api/history/ |
Query run history |
Example query payload
{
"model": "Device",
"app_label": "myapp",
"select_fields": ["id", "name", "status", "region"],
"filter_fields": {
"and_operation": [
{
"or_operation": [
{ "field": "status", "op": "is", "value": "active" },
{ "field": "status", "op": "is", "value": "maintenance" }
]
},
{
"or_operation": [
{ "field": "region", "op": "is", "value": "DE" },
{ "field": "region", "op": "is", "value": "AT" }
]
}
]
},
"page": 1,
"page_size": 100
}
UI capabilities
- Dashboard — model counts, saved query count and recent activity
- Query builder — field picker, nested
(a or b) and (x or y)filter groups, CSV export, JSON copy - Models browser — field types, nullability, filterable flags, relation inspection
- Saved queries — create, update, delete, bulk delete and run from the UI
- History — replay past runs, save from history, filter by model and time range
- Settings — page size, default app, theme
- Light and dark mode
Django admin
The package registers the following models in Django admin:
| Model | Description |
|---|---|
QLabUserSettings |
Per-user theme, page size and active tab |
SavedQuery |
Stored query payloads with metadata |
QueryRunHistory |
Execution log with status, duration and result snapshot |
Caching
model_exists() uses lru_cache for performance. The cache is cleared on
process restart. If you register new models at runtime, make sure to restart
your application server (e.g. Gunicorn) to reflect the changes.
Requirements
| Package | Version |
|---|---|
| Python | ≥ 3.9 |
| Django | ≥ 4.0 |
| djangorestframework | ≥ 3.14 |
| pydantic | ≥ 2.0 |
| drf-spectacular | ≥ 0.26 |
Frontend development
This section is for maintainers working on the UI itself. Package consumers do not need npm.
cd frontend
npm install
npm run dev # dev server with HMR
npm run build # write compiled assets to qlab/static/qlab/
License
MIT
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
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file django_qlab-0.4.1.tar.gz.
File metadata
- Download URL: django_qlab-0.4.1.tar.gz
- Upload date:
- Size: 124.9 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
85ad627e983b1757e279a369821b223749aa4771233bd5db79c17ced514452c5
|
|
| MD5 |
c5da11bc416edaebb26741c52de5f4b1
|
|
| BLAKE2b-256 |
723c78e2751a16ccc7918f52ce3783a1a2097666313cd9a2fd72ff8ae3cb9593
|
File details
Details for the file django_qlab-0.4.1-py3-none-any.whl.
File metadata
- Download URL: django_qlab-0.4.1-py3-none-any.whl
- Upload date:
- Size: 130.2 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
a571509d4aa96c5392b51b45e4c16e13b628a165bab5745d28489b7402ab8adb
|
|
| MD5 |
eb30b763851054a44bb7a6e991406192
|
|
| BLAKE2b-256 |
cc107d1c190e2890abd42c67ae4c2c52418af33ce169dbdf8ad22fba4122d5bb
|