Skip to main content

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.

PyPI version Python Django License: MIT


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

  1. pip install django-qlab
  2. Add qlab (and its dependencies) to INSTALLED_APPS
  3. Include qlab.urls in your URL config
  4. python manage.py migrate && python manage.py collectstatic
  5. 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

django_qlab-0.4.0.tar.gz (124.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_qlab-0.4.0-py3-none-any.whl (130.2 kB view details)

Uploaded Python 3

File details

Details for the file django_qlab-0.4.0.tar.gz.

File metadata

  • Download URL: django_qlab-0.4.0.tar.gz
  • Upload date:
  • Size: 124.8 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.12

File hashes

Hashes for django_qlab-0.4.0.tar.gz
Algorithm Hash digest
SHA256 ce56b37a0173baeb4873337e54177b695638551585d5dc73b02a6f330de27fe7
MD5 3ded11fa84b8b82cb85214ddbc3f97dc
BLAKE2b-256 ad0dc2d15aad299af86f922d81ce6303f73b9038b332cd237fa354cc1f456c7b

See more details on using hashes here.

File details

Details for the file django_qlab-0.4.0-py3-none-any.whl.

File metadata

  • Download URL: django_qlab-0.4.0-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

Hashes for django_qlab-0.4.0-py3-none-any.whl
Algorithm Hash digest
SHA256 6fdc7633e314cf78150718e986acd4765ce6e5984c46fa3dc499720e2defd69b
MD5 d670800e142ce5db330ba64b5e6886b7
BLAKE2b-256 3a16938233048c5ed3cb19a4449399adea051e882d4057c47ec3ceccb33c038c

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