djangoql

Advanced search language for the Django admin, with auto-completion, joins, and logical operators.

Library
PyPI
v0.19.1
1,139stars
MIT License

Repository Health

Pre-computed score based on development activity, maintenance, community, maturity, and trend momentum.How we score it →
44/100Fair
Development Activity4
Maintenance0
Community72
Maturity60
Momentum40

Technical Analysis

AI-assessed by reading the actual repository — architecture, code quality, innovation, and documentation.How we score it →
76/100Good
Architecture75
Code Quality78
Innovation70
Learning Curve80

DjangoQL replaces the plain-text Django admin search box with a small, Python-flavored query language. Instead of a single search string matched against a fixed list of fields, staff users write expressions like name = "foo" and author.email = "em@il" and written > "2017-01-30" — referencing model fields exactly as they’d appear in Python code, following relations with dot notation, and combining conditions with and/or and parentheses.

The library ships a browser-based auto-completion widget (built from a shared PLY lexer/grammar exposed to JavaScript) that suggests field names and value choices as you type, plus a schema layer (DjangoQLSchema) that lets developers restrict which models and fields are searchable, add computed/annotated fields, and customize how each field’s value is looked up. It works as a drop-in DjangoQLSearchMixin for any ModelAdmin, or as a .djangoql() queryset method for use outside the admin.

What You Get

  • A drop-in DjangoQLSearchMixin that replaces ModelAdmin search with a DjangoQL-powered search bar, optionally toggleable alongside the standard search_fields search
  • A JavaScript auto-completion widget that suggests field names, relations, and value choices live as the query is typed, backed by introspection and suggestion endpoints
  • A DjangoQLSchema class for scoping which models/fields are searchable, adding custom fields backed by annotations or fully custom ORM lookups, and controlling suggestion behavior per field
  • A .djangoql(query) queryset method (via DjangoQLQuerySet/apply_search) for running DjangoQL searches anywhere, not just in the admin
  • Typed field classes (IntField, FloatField, StrField, BoolField, DateField, DateTimeField, RelationField) that validate query values against the field’s Django type before building a Q object

Common Use Cases

  • Letting non-technical admin staff filter large tables by multiple fields and relations without needing a custom admin filter for every combination
  • Searching across foreign-key and many-to-many relations (e.g. author.last_name or groups.name) directly from the admin search bar
  • Exposing computed/annotated queryset fields (e.g. a groups_count annotation) as first-class searchable fields via a custom schema
  • Running the same advanced-search syntax outside the Django admin, in any view or management command, via the .djangoql() queryset method

Under The Hood

Architecture The codebase is organized as four cooperating layers: a PLY-based DjangoQLLexer/DjangoQLParser (djangoql/lexer.py, djangoql/parser.py) that turns a query string into an AST of Name/Comparison/Logical/Const/List nodes (djangoql/ast.py); a DjangoQLSchema (djangoql/schema.py) that recursively introspects a Django model’s relation graph into typed DjangoQLField instances and validates the AST against it; a queryset.py module that walks the validated AST and folds it into a Django Q object via build_filter, exposed as apply_search() and the DjangoQLQuerySet.djangoql() mixin method; and an admin.py integration layer (DjangoQLSearchMixin, DjangoQLChangeList) that wires the whole pipeline into ModelAdmin.get_search_results(), adds introspect/suggestions admin URLs, and falls back gracefully to Django’s error messages on FieldError/ValidationError/Postgres inet-comparison failures. A parallel completion-widget/ JS package (webpack-built) mirrors the grammar client-side to drive live auto-completion against those same introspect/suggestion endpoints.

Tech Stack The Python side depends on a single runtime package, ply>=3.8, for lexing/parsing, and integrates with Django via standard ModelAdmin/QuerySet/Q APIs with explicit compatibility shims (compat.py, try/except imports for re_path vs url, django.urls vs django.core.urlresolvers) spanning Django 1.8 through 6.0 and Python 2.7 through 3.14. The frontend widget is built with Babel (.babelrc) and Webpack (webpack.config.js), packaged and versioned independently via package.json/yarn.lock, and the compiled JS/CSS ship as Django static assets under djangoql/static/djangoql/.

Code Quality The test_project/core/tests/ suite covers the lexer, parser, AST, schema, queryset filtering, and admin integration in separate files (roughly 700 lines of tests), run against a Django test project via manage.py test core.tests. CI (.github/workflows/tests.yaml) runs this suite across an extensive Django/Python version matrix (Django 1.8 through 6.0 against matching Python 2.7–3.14 releases) plus a flake8 + isort lint gate before tests run, with setup.cfg pinning an 80-character line length and explicit import-ordering rules. Error handling is deliberate rather than swallowed: custom exception types (DjangoQLError, DjangoQLLexerError, DjangoQLParserError, DjangoQLSchemaError) carry line/column context, and the admin mixin explicitly catches and surfaces FieldError/ValidationError/DataError as user-facing admin messages instead of raising a 500.

What Makes It Unique Rather than bolting a search box onto Django admin, DjangoQL builds an actual small language — with its own lexer, grammar, and typed schema-validation pass — purpose-fit to Django’s model/relation graph, so a query like published = False or date_published = None is validated against real field types before it ever reaches the database. Extension points (get_lookup_name, get_lookup_value, a fully overridable get_lookup) let developers redefine what a field name means at the ORM level (custom annotations, computed lookups, cross-field logic) without forking the parser, which is a more structured escape hatch than most ad hoc admin search implementations offer.

Join founders buildingwith open source

Opinionated takes, migration guides, cost-saving tips, and insights from the open source ecosystem.

Subscribe on Substack
Join 750+ subscribers

Search