没有参数的依赖有什么作用?

What does Depends with no parameter do?

我正在尝试使用 fastapi 实现 JWT。 目前正在查看以下库 fastapi-users FastAPI JWT Auth

在这两种情况下,我都在方法参数中看到了 Depends()。 当参数中没有任何内容时,Depends 有什么作用?

https://github.com/frankie567/fastapi-users/blob/master/fastapi_users/router/auth.py

@router.post("/login")
    async def login(
        response: Response, credentials: OAuth2PasswordRequestForm = Depends()
    ):

https://indominusbyte.github.io/fastapi-jwt-auth/usage/basic/

@app.post('/login')
def login(user: User, Authorize: AuthJWT = Depends()):

我不明白什么时候参数中有一个函数,但是你能教我当没有 Depends 参数时它会做什么吗?

In both cases, I see Depends() in method parameter. What does Depends do when there is nothing in the parameter?

这是一个很好的问题。

假设您有以下代码。

from fastapi import FastAPI, Depends
from pydantic import BaseModel
from typing import Optional


class Location(BaseModel):
    city: str
    country: str
    state: str


app = FastAPI()


@app.post("/withoutdepends")
async def with_depends(location: Location):
    return location


@app.post("/withdepends")
async def with_depends(location: Location = Depends()):
    return lcoation

我们在两个不同的端点有相同的 Location 模型,一个使用 Depends 另一个不使用。

有什么区别?

由于 FastAPI 基于 OpenAPI 规范,我们可以开始发现与自动生成的 Swagger 文档的区别。

这是没有 Depends,它需要一个请求主体。

这是 with Depends,它希望它们作为查询参数。

这有什么用,它是如何工作的?

实际上,就是它,它需要一个 Callable

但是,当您将 Pydantic 模型Depends 一起使用时,它实际上会为 init __init__ 函数中的参数创建一个查询参数。

例如,这是我们上面使用的模型。

class Location(BaseModel):
    city: str
    country: str
    state: str

Depends变成这个。


class Location(BaseModel):
    def __init__(self, city: str, country: str, state: str) -> None:
        ...

然后它们将成为查询参数。这是 /withdepends 端点的 OpenAPI 架构。

"parameters": [
    {
        "required":true,
        "schema":{
            "title":"City",
            "type":"string"
        },
        "name":"city",
        "in":"query"
    },
    {
        "required":true,
        "schema":{
            "title":"Country",
            "type":"string"
        },
        "name":"country",
        "in":"query"
    },
    {
        "required":true,
        "schema":{
            "title":"State",
            "type":"string"
        },
        "name":"state",
        "in":"query"
    }
]

这是它为 /withoutdepends 端点创建的 OpenAPI 架构。

"requestBody": {
    "content":{
        "application/json":{
            "schema":{
                "$ref":"#/components/schemas/Location"
            }
        }
    },
    "required":true
}

结论

您可以使用相同的模型创建查询参数,而不是请求正文

Pydantic 模型对于参数为 +5 的情况非常有用。但它默认需要 请求主体 。但是 OpenAPI specification 不允许 GET 操作中的请求主体。正如规范中所说。

GET, DELETE and HEAD are no longer allowed to have request body because it does not have defined semantics as per RFC 7231.

因此,通过使用 Depends,您可以使用相同的模型为 GET 端点创建查询参数。

Depends() 没有参数只是 shortcut for classes as dependencies.

You see that we are having some code repetition here, writing CommonQueryParams twice:

commons: CommonQueryParams = Depends(CommonQueryParams)

FastAPI provides a shortcut for these cases, in where the dependency is specifically a class that FastAPI will "call" to create an instance of the class itself.

For those specific cases, you can do the following:

Instead of writing:

commons: CommonQueryParams = Depends(CommonQueryParams)

...you write:

commons: CommonQueryParams = Depends()

You declare the dependency as the type of the parameter, and you use Depends() as its "default" value (that after the =) for that function's parameter, without any parameter in Depends(), instead of having to write the full class again inside of Depends(CommonQueryParams).