Skip to content

[BUG] query params do not work #1564

@fraser-langton

Description

@fraser-langton

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"])

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions