-
-
Notifications
You must be signed in to change notification settings - Fork 532
Open
Description
Query params behaviour very hard to understand, default / optional values don't work. The open api shows them correcty as optional but ninja fails the validation
{
"detail": [
{
"type": "string_type",
"loc": [
"query",
"q"
],
"msg": "Input should be a valid string"
}
]
}I have attached a demo, including ones taken from the docs
import sys
from datetime import date
import django
from django.conf import settings
from django.core.management import execute_from_command_line
from django.urls import path
from pydantic import BaseModel
# Configure minimal Django settings
if not settings.configured:
settings.configure(
DEBUG=True,
SECRET_KEY="test-secret-key-for-demo",
ROOT_URLCONF=__name__,
ALLOWED_HOSTS=["*"],
INSTALLED_APPS=["django.contrib.contenttypes", "django.contrib.auth"],
MIDDLEWARE=["django.middleware.common.CommonMiddleware"],
APPEND_SLASH=True,
TEMPLATES=[
{
"BACKEND": "django.template.backends.django.DjangoTemplates",
"DIRS": [],
"APP_DIRS": True,
"OPTIONS": {},
}
],
)
django.setup()
# Import ninja AFTER Django is configured
from ninja import Field, NinjaAPI, Query, Schema
api = NinjaAPI()
@api.get("/example1")
def example_1(request, q: str | None = None):
"""
doesn't work
"""
return {"q": q}
@api.get("/example2")
def example_2(request, q: Query[str | None] = None):
"""
doesn't work
"""
return {"q": q}
@api.get("/example3")
def example_3(request, q: str | None = Query(None)):
"""
doesn't work
"""
return {"q": q}
class QueryParams1(Schema):
q: str | None = None
@api.get("/example4")
def example_4(filters: Query[QueryParams1]):
"""
doesn't work
"""
return {"q": filters.q}
@api.get("/example5")
def example_5(request, filters: Query[QueryParams1]):
"""
works (requires request?)
"""
return {"q": filters.q}
class QueryParams2(BaseModel):
q: str | None = None
@api.get("/example5")
def example_5(request, filters: Query[QueryParams2]):
"""
pydnatic doesn't work
"""
return {"q": filters.q}
weapons = ["Ninjato", "Shuriken", "Katana", "Kama", "Kunai", "Naginata", "Yari"]
@api.get("/weapons")
def list_weapons(request, limit: int = 10, offset: int = 0):
return weapons[offset : offset + limit]
@api.get("/weapons/search")
def search_weapons(request, q: str, offset: int = 0):
"""
openapi shows
"""
results = [w for w in weapons if q in w.lower()]
return results[offset : offset + 10]
@api.get("/example")
def example(request, s: str = None, b: bool = None, d: date = None, i: int = None):
"""
openapi shows optional, ninja throws error
"""
return [s, b, d, i]
class Filters(Schema):
limit: int = 100
offset: int = None
query: str = None
category__in: list[str] = Field(None, alias="categories")
@api.get("/filter")
def events(request, filters: Query[Filters]):
"""
works
"""
return {"filters": filters.dict()}
urlpatterns = [path("api/", api.urls)]
if __name__ == "__main__":
execute_from_command_line([sys.argv[0], "runserver", "8004"])laleye and dtatarkin
Metadata
Metadata
Assignees
Labels
No labels