I have the following in my main.py
:
from fastapi import FastAPI, Request
from fastapi.responses import HTMLResponse
from fastapi.middleware.gzip import GZipMiddleware
from fastapi.templating import Jinja2Templates
from fastapi.staticfiles import StaticFiles
from my_app.web.views import default
app = FastAPI()
app.add_middleware(GZipMiddleware, minimum_size=500)
app.include_router(default.router)
#app.include_router(data_mgr_view.router)
app.mount("/static", StaticFiles(directory="static"), name="static")
app.mount("/templates", Jinja2Templates(directory="templates"), name="templates")
@app.get('/test')
async def test():
return "test successful"
This works fine. I can hit the URL at localhost:5000/test
and it returns expected string.
Now I have this file default.py
whose handlers I want to be based off root:
import sys, traceback
import pandas as pd
from fastapi import APIRouter, Request, Query
from my_app.web.models.response_data import ResponseData
from my_app.data.providers.internals_provider import MktInternalsProvider
from my_app.config import tmplts
router = APIRouter(prefix="")
@router.route('/')
async def root(request: Request):
context = {"title":"Playground", "content":f"Place for my charts, studies, etc..."}
return tmplts.TemplateResponse(request=request, name="index.html", context=context)
@router.route('/test2')
async def test2():
return "test2 success"
The first method works fine when I hit localhost:5000/
. The second method throws an exception when I hit localhost:5000/test2
:
Traceback (most recent call last):
File "/usr/local/lib/python3.11/site-packages/uvicorn/protocols/http/httptools_impl.py", line 411, in run_asgi
result = await app( # type: ignore[func-returns-value]
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.11/site-packages/uvicorn/middleware/proxy_headers.py", line 69, in __call__
return await self.app(scope, receive, send)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/local/lib/python3.11/site-packages/fastapi/applications.py", line 1054, in __call__
await super().__call__(scope, receive, send)
File "/usr/local/lib/python3.11/site-packages/starlette/applications.py", line 123, in __call__
await self.middleware_stack(scope, receive, send)
File "/usr/local/lib/python3.11/site-packages/starlette/middleware/errors.py", line 186, in __call__
raise exc
File "/usr/local/lib/python3.11/site-packages/starlette/middleware/errors.py", line 164, in __call__
await self.app(scope, receive, _send)
File "/usr/local/lib/python3.11/site-packages/starlette/middleware/gzip.py", line 24, in __call__
await responder(scope, receive, send)
File "/usr/local/lib/python3.11/site-packages/starlette/middleware/gzip.py", line 44, in __call__
await self.app(scope, receive, self.send_with_gzip)
File "/usr/local/lib/python3.11/site-packages/starlette/middleware/exceptions.py", line 65, in __call__
await wrap_app_handling_exceptions(self.app, conn)(scope, receive, send)
File "/usr/local/lib/python3.11/site-packages/starlette/_exception_handler.py", line 64, in wrapped_app
raise exc
File "/usr/local/lib/python3.11/site-packages/starlette/_exception_handler.py", line 53, in wrapped_app
await app(scope, receive, sender)
File "/usr/local/lib/python3.11/site-packages/starlette/routing.py", line 756, in __call__
await self.middleware_stack(scope, receive, send)
File "/usr/local/lib/python3.11/site-packages/starlette/routing.py", line 776, in app
await route.handle(scope, receive, send)
File "/usr/local/lib/python3.11/site-packages/starlette/routing.py", line 297, in handle
await self.app(scope, receive, send)
File "/usr/local/lib/python3.11/site-packages/starlette/routing.py", line 77, in app
await wrap_app_handling_exceptions(app, request)(scope, receive, send)
File "/usr/local/lib/python3.11/site-packages/starlette/_exception_handler.py", line 64, in wrapped_app
raise exc
File "/usr/local/lib/python3.11/site-packages/starlette/_exception_handler.py", line 53, in wrapped_app
await app(scope, receive, sender)
File "/usr/local/lib/python3.11/site-packages/starlette/routing.py", line 72, in app
response = await func(request)
^^^^^^^^^^^^^
TypeError: test2() takes 0 positional arguments but 1 was given
When using APIRouter
(see APIRouter
class docs as well), you shouldn't be using the route
decorator/method (which, by the way, appears to be deprecated in Starlette's source code, and its usage is discouraged).
You should instead use the api_route
decorator. Example:
from fastapi import FastAPI
from fastapi import APIRouter
router = APIRouter()
@router.api_route('/')
async def root():
return {"op": "root"}
app = FastAPI()
app.include_router(router)
The default HTTP method allowed for that decorator is GET
, but you could customize it as desired, using the methods
parameter in the decorator. Example:
@router.api_route('/', methods=["GET", "POST"])
Alternatively, you could simply use @router.get
, @router.post
, etc., decorators as usual. Example:
@router.get('/')
@router.post('/')
I would highly recommend having a look at this answer, this answer, as well as this answer and this answer, which are related to the subject and should prove helpful.