1

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
1
  • async def test2(): -> async def test2(request : Request): Commented May 12, 2024 at 7:15

2 Answers 2

2

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.

Sign up to request clarification or add additional context in comments.

2 Comments

that worked. i was following what i thought was latest docs. thanks much!
Valid answer, PSF needs to really take care of their error messaging.
0

this will work: Provide a method with router like get or post

@router.get('/test2')
async def test2():
    return "test2 success"

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.