Fastapi: [BUG] - FastAPI Routes don't work with Starlette's request.url_for when query params are passed

Created on 21 Jun 2019  Â·  3Comments  Â·  Source: tiangolo/fastapi

Describe the bug
It looks like Starlette's routes are not populating self.param_convertors so, when using request.url_for and passing query parameters, the route does not match (I think this is the code) and url_for fails with a NoMatchFound

To Reproduce
I think this view will do it, sorry if I've elided anything important:

@router.get("/", name='events_list')
def list_object(
    offset: int = Query(0),
    request: Request = Required
):
            next = request.url_for('events_list', offset=42)
            ...

Expected behavior
I'd expect url_for to return something like 'http://testserver/events/?offset=42'

Actual behavior

../diary/api/events.py:57: in list_object
    next = request.url_for('events_list', offset=42)
/Users/chris/Library/Caches/pypoetry/virtualenvs/diary-py3.7/lib/python3.7/site-packages/starlette/requests.py:117: in url_for
    url_path = router.url_path_for(name, **path_params)
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <fastapi.routing.APIRouter object at 0x105e855f8>, name = 'events_list'
path_params = {'offset': 42}
route = <fastapi.routing.APIRoute object at 0x106c5ecf8>

    def url_path_for(self, name: str, **path_params: str) -> URLPath:
        for route in self.routes:
            try:
                return route.url_path_for(name, **path_params)
            except NoMatchFound:
                pass
>       raise NoMatchFound()
E       starlette.routing.NoMatchFound

Environment:

  • FastAPI Version [e.g. 0.3.0], get it with: 0.30.0
bug

Most helpful comment

I see you discovered the problem and requested the feature here: https://github.com/encode/starlette/issues/560

So I'll close this issue now, as that would actually be a Starlette feature request.


For completeness, for anyone coming afterwards, request.url_for() receives path parameters, not query parameters.

All 3 comments

kind of remember having been bitten by this
worth trying to not use name but _name @router.get("/", _name='events_list')

edit: scrap that it was when I had name in the path
On Fri, Jun 21, 2019 at 9:27 AM Chris Withers notifications@github.com
wrote:

Describe the bug
It looks like Starlette's routes are not populating self.param_convertors
so, when using request.url_for and passing query parameters, the route
does not match (I think this is the code
https://github.com/encode/starlette/blob/8c8cc2ec0a5cb834a9a15b871ae8b480503abb67/starlette/routing.py#L190)
and url_for fails with a NoMatchFound

To Reproduce
I think this view will do it, sorry if I've elided anything important:

@router.get("/", name='events_list')
def list_object(
offset: int = Query(0),
request: Request = Required
):
next = request.url_for('events_list', offset=42)
...

Expected behavior
I'd expect url_for to return something like '
http://testserver/events/?offset=42'

Actual behavior

../diary/api/events.py:57: in list_object
next = request.url_for('events_list', offset=42)
/Users/chris/Library/Caches/pypoetry/virtualenvs/diary-py3.7/lib/python3.7/site-packages/starlette/requests.py:117: in url_for
url_path = router.url_path_for(name, **path_params)


self = , name = 'events_list'
path_params = {'offset': 42}
route =

def url_path_for(self, name: str, **path_params: str) -> URLPath:
    for route in self.routes:
        try:
            return route.url_path_for(name, **path_params)
        except NoMatchFound:
            pass
  raise NoMatchFound()

E starlette.routing.NoMatchFound

Environment:

  • FastAPI Version [e.g. 0.3.0], get it with: 0.30.0

—
You are receiving this because you are subscribed to this thread.
Reply to this email directly, view it on GitHub
https://github.com/tiangolo/fastapi/issues/323?email_source=notifications&email_token=AAINSPSFZHB2SRXYNPHHGGDP3R7G5A5CNFSM4H2NXBQKYY3PNVWWK3TUL52HS4DFUVEXG43VMWVGG33NNVSW45C7NFSM4G24THVQ,
or mute the thread
https://github.com/notifications/unsubscribe-auth/AAINSPV2YX74QQHVECCWAJTP3R7G5ANCNFSM4H2NXBQA
.

--
benoit barthelet
http://pgp.mit.edu/pks/lookup?op=get&search=0xF150E01A72F6D2EE

I see you discovered the problem and requested the feature here: https://github.com/encode/starlette/issues/560

So I'll close this issue now, as that would actually be a Starlette feature request.


For completeness, for anyone coming afterwards, request.url_for() receives path parameters, not query parameters.

For anyone interested in doing this themselves, the following code may be useful.

https://gist.github.com/jacksmith15/b220686eae16d52a10ef59b5de09c213

This goes a bit further than starlette's feature request, as it leverages FastAPI's parameter validation to prevent bad URLs being generated.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

zero0nee picture zero0nee  Â·  3Comments

updatatoday picture updatatoday  Â·  3Comments

devtud picture devtud  Â·  3Comments

danielgtaylor picture danielgtaylor  Â·  3Comments

DrPyser picture DrPyser  Â·  3Comments