vitalik / django-ninja

💨 Fast, Async-ready, Openapi, type hints based framework for building APIs
https://django-ninja.dev
MIT License
6.66k stars 396 forks source link

Path parameters, order matters #1123

Open santigandolfo opened 3 months ago

santigandolfo commented 3 months ago

Is there a way to add something like this in the docs?

One of my team mates was faced with this problem and couldn't understand why when making a request to /stores/verticals the request was instead being processed by /stores/{store_id} (and returning a 422 error because store_id should be an int)

MRE:

from django.urls import path
from ninja import NinjaAPI

api = NinjaAPI()

@api.get("/stores/{store_id}")
def get_store(request, store_id: int):
    print(f"Store {store_id}")

@api.get("/stores/verticals")
def get_stores_verticals(request):
    print("Stores verticals")

urlpatterns = [
    path("api/", api.urls),
]
pmdevita commented 3 months ago

You can do

@api.get("/stores/{int:store_id}")
def get_store(request, store_id: int):
    print(f"Store {store_id}")

Ninja will take path params the same way Django url routing normally does. This should fix this problem. This definitely needs to be documented better, it's sort of documented here but it's not clear that this is the solution to this problem.

santigandolfo commented 3 months ago

You can do

@api.get("/stores/{int:store_id}")
def get_store(request, store_id: int):
    print(f"Store {store_id}")

Ninja will take path params the same way Django url routing normally does. This should fix this problem. This definitely needs to be documented better, it's sort of documented here but it's not clear that this is the solution to this problem.

Wow, somehow I completely missed that part in the docs. And the worst part is that I tried doing the reverse thing, "/stores/{store_id:int}").

Although, this wouldn't work for things other that ints and uuids, right? For example ULIDs, UUIDs without the dashes, etc.

pmdevita commented 3 months ago

You might be able to try registering your own custom path converters https://docs.djangoproject.com/en/5.0/topics/http/urls/#registering-custom-path-converters Since I think Ninja is just using Django's own path resolving this should work