My main goal is to define validation rules for name tags only once and reuse it later in diffrent places (e.g. query params, resource path).
For that, i try to use pydantic model with __root__ as fastapi query/path parameter.
This and this looks like answer but unfortunately for some reason non primitives fields in query model treats as body fields
The base code:
from typing import Annotated
from fastapi import FastAPI, Query
from pydantic import BaseModel, Field
app = FastAPI()
class TagName(BaseModel):
    __root__: str = Field(example='aot', max_length=128, min_length=3)
Then i try to use the following ways to tell fastapi treat TagName as query param:
Using Query
@app.patch('/')
async def change_tag_by_name(
    query: Annotated[TagName, Query()],
):
    ...
AssertionError: Param: query can only be a request body, using Body()`
Using Depends with simple class
class ChangeTagByNameQuery:
    def __init__(self, tag: TagName):
        self.tag = tag
@app.patch('/')
async def change_tag_by_name(
    query: Annotated[TagName, Depends(ChangeTagByNameQuery)],
):
    ...
It successfully runs, but fastapi just includes ChangeTagByNameQuery.name into the body schema:
...
"paths":{
    "/":{
      "patch":{
        "summary":"Change Tag By Name",
        "operationId":"change_tag_by_name__patch",
        "requestBody":{
          "content":{
            "application/json":{
              "schema":{
                "$ref":"#/components/schemas/TagName"
              }
            }
          },
          "required":true
        },
...
The main