LLM-backed, structured JSON output, schema-aware natural language queries for Django ORM
Project description
Django YOLOQuery
LLM‑Based Queries for the Django ORM
⚠️ This is just a Proof-of-Concept
Why?
I want to see how badly LLMs can be integrated into our system
TL;DR
authors = Author.objects.ai_query("get all authors named John")
books = Book.objects.ai_query("books published after 2020 by American authors")
recent = Author.objects.ai_query("authors with books published in the last 5 years")
Install
pip install django-yoloquery
Configure
Add to INSTALLED_APPS and set a few knobs in settings.py.
INSTALLED_APPS = [
# ... your apps ...
'django_yoloquery',
]
# Required: OpenAI API key (or set env OPENAI_API_KEY)
YOLOQUERY_OPENAI_API_KEY = "sk-..."
# Optional (shown with defaults)
YOLOQUERY_SCHEMA_DEPTH = 1 # how far to traverse relations
YOLOQUERY_INCLUDE_REVERSE = True # include reverse relations (related_name / _set)
YOLOQUERY_LLM_MODEL = "gpt-4o-mini" # pick your OpenAI model
YOLOQUERY_AUTO_INSTALL = ["myapp.*"] # auto‑YOLO patch models
🔑 If
YOLOQUERY_OPENAI_API_KEYis not set, YOLOQuery falls back to theOPENAI_API_KEYenvironment variable.
Manual Wiring (if you don’t want auto‑patch)
from django.db import models
from django_yoloquery import YoloManager
class Author(models.Model):
name = models.CharField(max_length=200)
country = models.CharField(max_length=100)
birth_date = models.DateField()
objects = YoloManager() # manual install
class Book(models.Model):
title = models.CharField(max_length=200)
authors = models.ManyToManyField(Author, related_name="books")
published_date = models.DateField()
isbn = models.CharField(max_length=13)
Auto‑Installation Patterns
YOLOQuery can monkey‑patch all the things at startup. Patterns are case‑sensitive app labels; model name matching is case‑insensitive.
YOLOQUERY_AUTO_INSTALL = [
"myapp.*", # all models in myapp
"blog.Post", # just that one model
"*", # YOLO EVERYTHING (seriously?)
]
When auto‑installed:
- The model’s default manager (
.objects) is replaced with a YOLO manager. - The original manager is saved as
._orig_objects. - A
.yoloalias also points at the YOLO manager because branding.
What the LLM Sees
YOLOQuery builds a JSON description of your model + related models (depth configurable, reverse rels optional). Example schema snippet for Author:
{
"root_model": "Author",
"app_label": "myapp",
"models": {
"Author": {
"fields": {
"name": {"type": "CharField", "null": false},
"country": {"type": "CharField", "null": false},
"birth_date": {"type": "DateField", "null": false}
},
"relationships": {
"books": {"type": "REV", "to": "Book"}
}
},
"Book": {
"fields": {
"title": {"type": "CharField", "null": false},
"published_date": {"type": "DateField", "null": false}
},
"relationships": {
"authors": {"type": "M2M", "to": "Author"}
}
}
}
}
Structured JSON Contract
The model must return JSON like:
{
"status": "ok",
"logic": "and", // or "or"
"filters": [
{"path": "name", "op": "iexact", "value": "John"},
{"path": "books__published_date", "op": "gt", "value": "2020-01-01"}
],
"order_by": ["-published_date"], // optional
"limit": 10 // optional
}
If the request can’t be translated (missing info / nonsense / hallucination danger), the model must respond:
{"status": "error", "message": "Missing value for field 'name'"}
YOLOQuery will turn that into an AIQueryLLMError (attached to an empty QuerySet unless raise_errors=True).
Supported Query Concepts
| You Say | LLM Might Output | Django Filters | |
|---|---|---|---|
| "authors named john" | name iexact John |
name__iexact="John" |
|
| "authors from usa or canada" | logic=or + country in [USA, Canada] | `Q(country__iexact="USA") | Q(country__iexact="Canada")` |
| "books published after 2020" | published_date gt 2020-01-01 | published_date__gt=date(2020,1,1) |
|
| "authors with books after 2020" | books__published_date gt 2020-01-01 | join across reverse M2M | |
| "top 10 newest books" | order_by=-published_date, limit=10 | .order_by('-published_date')[:10] |
Error Handling
YOLOQuery errs on the side of not doing something dumb:
qs = Author.objects.ai_query("authors where") # incomplete!
if hasattr(qs, 'ai_error'):
print("LLM said nope:", qs.ai_error)
Raise immediately:
Author.objects.ai_query("authors where", raise_errors=True)
# AIQueryLLMError: LLM could not translate query.
Testing (No API Calls)
from django_yoloquery import DummyLLM
DUMMY_RESPONSES = {
"authors named John": {
"status": "ok",
"filters": [{"path": "name", "op": "iexact", "value": "John"}]
},
"name is": {
"status": "error", "message": "Missing value for name"
},
}
dummy = DummyLLM(DUMMY_RESPONSES)
qs = Author.objects.ai_query("authors named John", llm=dummy)
assert list(qs.values_list("name", flat=True)) == ["John"]
FAQ (Frequently Asked Questions No One Asked Yet)
Q: Does this belong in production? A: The library literally has YOLO in the name.
Q: Will it leak my schema to OpenAI? A: Yes, that’s how it works. Use stub schemas or anonymized field names if that’s a problem.
Q: Can I use Anthropic / local models? A: PRs welcome. Right now it’s OpenAI only; we rely on JSON Schema format.
Q: What if the model hallucinates? A: We validate every field + op; hallucinations become errors instead of DB hits. (We try, anyway.)
Q: Does it understand dates like "last quarter"? A: Depends on the model; we just validate output.
Requirements
- Python 3.8+
- Django 3.2+
openai>=1.0.0- OpenAI API key
License
MIT – see LICENSE.
Project details
Release history Release notifications | RSS feed
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_yoloquery-0.1.4.tar.gz.
File metadata
- Download URL: django_yoloquery-0.1.4.tar.gz
- Upload date:
- Size: 15.9 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.12.9
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
a389c378bdbc069bb3a1dcc301d2823a3cefc693c7f1e0f7a0be17a130d6f058
|
|
| MD5 |
1c07e750be68f26f655b5809e775339b
|
|
| BLAKE2b-256 |
d06e20673cefdffa636ed3ea5de37b884bf6587a8497ead6d61bd4263bc960fe
|
Provenance
The following attestation bundles were made for django_yoloquery-0.1.4.tar.gz:
Publisher:
release.yml on zhuang42/django-yoloquery
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
django_yoloquery-0.1.4.tar.gz -
Subject digest:
a389c378bdbc069bb3a1dcc301d2823a3cefc693c7f1e0f7a0be17a130d6f058 - Sigstore transparency entry: 289034225
- Sigstore integration time:
-
Permalink:
zhuang42/django-yoloquery@c8d46782ff5e3c97b8eb15b1d09206a9d9d12fff -
Branch / Tag:
refs/heads/main - Owner: https://github.com/zhuang42
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@c8d46782ff5e3c97b8eb15b1d09206a9d9d12fff -
Trigger Event:
workflow_dispatch
-
Statement type:
File details
Details for the file django_yoloquery-0.1.4-py3-none-any.whl.
File metadata
- Download URL: django_yoloquery-0.1.4-py3-none-any.whl
- Upload date:
- Size: 13.0 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.12.9
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
fb91bef4049762c43e9e1a26d59919939d3a4a33c088720dff1e9417ca9b0ae8
|
|
| MD5 |
7f5e42b5495683dd9471c09562f430cd
|
|
| BLAKE2b-256 |
034e06ff08ed27c43b88400ad5624a14f8504d132410fdf77d6178c43bdd8d4b
|
Provenance
The following attestation bundles were made for django_yoloquery-0.1.4-py3-none-any.whl:
Publisher:
release.yml on zhuang42/django-yoloquery
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
django_yoloquery-0.1.4-py3-none-any.whl -
Subject digest:
fb91bef4049762c43e9e1a26d59919939d3a4a33c088720dff1e9417ca9b0ae8 - Sigstore transparency entry: 289034261
- Sigstore integration time:
-
Permalink:
zhuang42/django-yoloquery@c8d46782ff5e3c97b8eb15b1d09206a9d9d12fff -
Branch / Tag:
refs/heads/main - Owner: https://github.com/zhuang42
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@c8d46782ff5e3c97b8eb15b1d09206a9d9d12fff -
Trigger Event:
workflow_dispatch
-
Statement type: