FastAPI library (Python web framework) basic usage guide (2)

Core functions

Define routes

There are two main ways to define routes in FastAPI, one is to use the FastAPI application instance method (for exampleapp.get()), and the other is to use a decorator (for example @app.get()), their usage and functions are slightly different.

  • Method 1: Using FastAPI application instance

    app.get()Methods such as , app.post() are used to define routes directly on the application instance.

    These methods accept a path string and a processing function as parameters, mapping the specified path to the corresponding processing function for processing requests on that path.

    This approach is suitable for defining routes globally and adding routes directly to the application.

    from fastapi import FastAPI
    
    def read_root():
        return {
          
          "message": "Hello, World"}
    
    app = FastAPI()
    app.get("/", read_root)
    
  • Way 2: Use decorators

    @app.get()Decorator syntax such as , @app.post(), etc. is used to add decorators above routing processing functions to associate the processing functions with specific paths and HTTP methods.

    The decorator method allows you to use decorators directly on the route processing function to define attributes such as paths, HTTP methods, and response models.

    This method is more intuitive and concentrates routing-related information on the processing function, making the code easier to read and maintain. Suitable for defining routes in a local scope.

    from fastapi import FastAPI
    
    app = FastAPI()
    
    @app.get("/")
    def read_root():
        return {
          
          "message": "Hello, World"}
    
  • Extension: a way to match all paths

    @app.get("/files/{file_path:path}")  	# :path 代表任意路径
    async def read_file(file_path: str):
        return {
          
          "file_path": file_path}
    

routing group

  • FastAPI allows routing to be organized into groups for better organization and management of API endpoints. This is particularly useful for applications with multiple related routes. Grouping keeps code clear and maintainable.

    Route grouping helps keep your code clean and readable, and also allows for better organization and presentation of API endpoints in documentation.

    You can create multiple groups according to your needs, put related routes together in the group, and you can also group the routes into different modules. For example, you can create a items.py file , which contains all items-related routes, is then imported in the main function modulemain.py and adds the grouping to the application.

  • APIRouter module method:

    • APIRouter(): Create a routing group instance
  • FastAPI Module methods:

    • include_router() : Add grouping to the application
      • router Parameters: Specify the routing group. Default parameters, required
      • prefix Parameter: Specify the prefix path of the group, optional transmission, the default is ""
      • tags Parameters: Specify grouping tags to facilitate documentation and classification
  • Example

    from fastapi import FastAPI, APIRouter
    
    app = FastAPI()
    
    # 创建一个路由分组
    router = APIRouter()
    
    # 将路由添加到分组
    @router.get("/")
    def read_root():
        return {
          
          "message": "Root"}
    
    @router.get("/items/")
    def read_items():
        return {
          
          "message": "Items"}
    
    # 将分组添加到应用程序
    app.include_router(router, prefix="/group1", tags=["Group 1"])
    
    # 创建另一个路由分组
    router2 = APIRouter()
    
    @router2.get("/")
    def read_another_root():
        return {
          
          "message": "Another Root"}
    
    @router2.get("/things/")
    def read_things():
        return {
          
          "message": "Things"}
    
    # 将第二个分组添加到应用程序
    app.include_router(router2, prefix="/group2", tags=["Group 2"])
    

path parameters

Declare path parameters

  • Path parameters: FastAPI declares dynamic path parameters by adding {} on both sides of the path parameters.

    @app.get("/items/{item_id}")
    def read_item(item_id: int):
        return {
          
          "item_id": item_id}
    

    The value of path parameteritem_id will be used as parameteritem_id passed to the function.

    • If item_id does not declare (restrict) the type, you can enter either a string or a number, but it will be converted to a string by default.
    • If item_id declares (restricts) the type, parameters can only be passed according to the type declared in advance
  • Routes containing path parameters must be declared after a normal path with the same path prefix!

    As an example, assume there are two existing paths with the same path prefix:

    • /users/me, a common path used to obtain data about the current user
    • /users/{user_id} , a route containing path parameters used to obtain data about a specific user by user ID

    Since path operations are run sequentially, you need to ensure that the path /users/me is declared before the path /users/{user_id}!

    Otherwise, the path of /users/{user_id} will also match /users/me, "thinking" that it is receiving a value of "me" a>user_id parameter.

    from fastapi import FastAPI
     
    app = FastAPI()
     
    @app.get("/users/me")
    async def read_user_me():
        return {
          
          "user_id": "the current user"}
     
    @app.get("/users/{user_id}")
    async def read_user(user_id: str):
        return {
          
          "user_id": user_id}
    
  • default value

    Sometimes you only need to pass several common and fixed valid values ​​to the path parameters, then you can customize the default value through enumeration .

    Note: Enums are available in Python starting with 3.4 version.

    from enum import Enum
    
    # 创建一个 Enum 类
    class ModelName(str, Enum):
        yinyu = "yinyu_v"
        s1 = "s1_v"
        s2 = "s2_v"
        
    # 包含枚举的路径参数
    ## 路径参数 model_name 的值将传递给函数 get_model 的参数 model_name,并且这个值的取值范围只能是 ModelName 枚举类中类属性的值。
    @app.get("/models/{model_name}")
    async def get_model(model_name: ModelName):
        # 第 1 种判断方式
        if model_name is ModelName.yinyu:
            return {
          
          "model_name": model_name, "message": "yinyu get"}
        # 第 2 种判断方式,效果一样
        if model_name.value == "s1_name":
            return {
          
          "model_name": model_name, "message": "s1 get"}
        else:
            return {
          
          "model_name": ModelName.s2, "message": "s2 get"}
    

fastapi.Path (verification path parameters)

In FastAPI, fastapi.Path is a class used to declare path parameters. It provides more parameter configuration options and allows defining the type, default value, and verification of path parameters. Rules etc. Use fastapi.Path for more fine-grained control over the behavior of path parameters.

Commonly used optional parameters:

  • default:Specifies the default value of the path parameter.

    Note: Since the path parameter is always required, if you want to pass the default parameter, you can only set default=... to explicitly mark it as a required parameter.

  • title: In automatically generated API documentation, used to display the title of the path parameter to provide better documentation.

  • description: In automatically generated API documents, used to display detailed descriptions of path parameters and provide more detailed documentation.

  • min_length and max_length: used to limit the string length range of path parameters.

  • min and max: used to limit the numerical range of path parameters, suitable for numeric path parameters.

  • regex: Use regular expressions to verify the value of path parameters. You can use regular expressions in string form.

  • deprecated: Marks the path parameter as deprecated to indicate to users that it should no longer be used.

  • example: In automatically generated API documentation, used to provide example values ​​for path parameters to help users understand how to use the parameter.

  • gt, ge, lt, le: used to set the size comparison of numeric type path parameters, respectively indicating greater than , greater than or equal to, less than, less than or equal to.

  • const: Set the path parameter to a constant value, which can be used to implement some specific route matching requirements.


query parameters

Declare query parameters

  • query parameters

    In web development, query parameters (Query Parameters) are a way to pass additional information to the server through parameter key-value pairs in the URL. These parameters are usually used for operations such as filtering, sorting, paging, etc.

    Query parameters usually appear after the question mark (?) in the URL. Each query parameter consists of a parameter name and a parameter value, connected with an equal sign (=). Use an ampersand (&) to separate multiple query parameters.

  • FastAPI declaration query parameters:

    Declaring other function parameters that are not path parameters in the parameter list of the routing function will be Automaticallyinterpreted asquery parameters!

    Query parameters can be set to default values:

    • If a default value is set, this parameter is optional. Default value can be set to None
    • If the default value is not set, this parameter must be passed. If it is not passed, an error will be reported.

    FastAPI can add parameters directly to the parameter list of the routing function to obtain query parameters (default values ​​can be set, if not set default values If so, an error will be reported if the meeting is not sent)

    @app.get("/items/{item_id}")
    def read_item(item_id: int, q: str = None):		# q是一个查询参数,可以接受字符串类型的值
        return {
          
          "item_id": item_id, "q": q}
    
    # 调用:localhost:8000/items/2?q=hhh
    
  • bool type conversion

    Declared as a bool type query parameter, the passed parameters can be automatically converted to True< /span>


fastapi.Query (verify query parameters)

  • typing.Union: is a type hint tool in Python, used to represent the union of multiple types. It is usually used with the Union type.

    In type annotations, you can use typing.Union to explicitly specify that the type of a variable can be one of multiple types.

  • fastapi.Query: is a tool in the FastAPI framework forprocessing query parameters, and Allows specifying various parameters to control query parameter types, default values, validation, etc. The following are some commonly used optional parameters:

    • default:Specifies the default value of query parameters. If the query parameter is not provided in the request, the default value will be used. Parameters can be passed by location.

      Declared as required parameters:

      • Method 1: If the default value is not specified, the parameters must be passed.

      • Method 2: Specifydefault=...

      • Method 3: Specifydefault=Required

        Note: A guide package is requiredfrom pydantic import Required

    • title: Used for titles in automatically generated API documentation to make the documentation clearer and easier to understand.

    • description: Display detailed descriptions of query parameters in automatically generated API documentation.

    • alias: Specifies the alias of the query parameter. This parameter can be used when you want to use a different name to refer to query parameters in a function.

    • regex: Validate query parameters using regular expressions. Only parameter values ​​matching the regular expression will be accepted.

    • min_length and max_length: Limit the minimum and maximum length of query parameter values.

    • min and max: Limit the minimum and maximum query parameter values ​​(only applies to numeric type parameters).

    • gt, ge, lt, le: used to specify greater than, greater than or equal to, less than, and A value less than or equal to (only applicable to numeric type parameters).

    • multiple: Specifies whether the query parameter can have multiple values, that is, whether multiple query parameters with the same name are allowed.

      Generally used for list type query parameters

    • deprecated: Specifies whether the query parameter is deprecated.

      If set to True, a message that this parameter has been deprecated will be displayed in the automatically generated API documentation.

  • Code example:

    from typing import Union
    from fastapi import FastAPI,Query
    
    @app.get("/items21/")
    async def read_items(q: Union[str, None] = Query(default=None),
                         a: str = Query(default=None, max_length=50, min_length=3)
                         b: Union[str, None] = Query(default=None, regex="^fixedquery$")
                        ):
        query_items = {
          
          "q": q}
        return query_items
    

Request body and response model

  • Request body

    The request body can be easily processed using the Pydantic library to define the data model.

    from pydantic import BaseModel
    
    # 定义Item模型
    class Item(BaseModel):
        name: str
        description: str = None
        price: float
        tax: float = None
    
    @app.post("/items/")
    def create_item(item: Item):	# 使用Item模型定义了请求体的结构,并将其用作create_item函数的参数
        return item
    
  • response model

    By setting the response_model parameter for the route, you can define the structure of the response data.

    from pydantic import BaseModel
    
    class Item(BaseModel):
        name: str
        description: str = None
        price: float
        tax: float = None
    
    @app.post("/items/", response_model=Item)
    def create_item(item: Item):
        return item
    

dependency injection

  • FastAPI supports dependency injection, which makes it easy to manage and reuse code.

    In FastAPI, dependency injection is a powerful feature that allows functionality (such as database connections, validation logic, etc.) to be injected into route processing functions to better organize and manage code, and achieve decoupling and testability .

    Dependency injection enables providing dependencies to functions when needed, rather than creating these dependencies inside the function.

    The advantage of dependency injection is that it can separate complex logic from route processing functions, making the code clearer and maintainable.

    from fastapi import FastAPI, Depends
    
    app = FastAPI()
    
    # 依赖项,模拟数据库连接
    def get_db_connection():
        db_connection = "fake_db_connection"
        return db_connection
    
    # 路由处理函数,注入依赖项
    @app.get("/items/")
    async def read_items(db: str = Depends(get_db_connection)):
        return {
          
          "message": "Items retrieved", "db_connection": db}
    

Exception handling

  • Handle errors in your application with custom exception handlers

    from fastapi import HTTPException
    
    @app.get("/items/{item_id}")
    def read_item(item_id: int):
        if item_id < 1:
            raise HTTPException(status_code=400, detail="Item not found")
        return {
          
          "item_id": item_id}
    

File Upload

  • Use fastapi.UploadFile type to receive uploaded file data

    from fastapi import FastAPI, UploadFile
    from fastapi.staticfiles import StaticFiles
    import os
    
    app = FastAPI()
    
    # 配置静态文件路径
    app.mount("/static", StaticFiles(directory="static"), name="static")
    
    @app.post("/file_upload")
    async def file_upload(file: UploadFile):
        # 接收文件
        res = await file.read()
    
        # 写到本地
        predict_img_path = os.path.join('static', file.filename)
        with open(predict_img_path, "wb") as f:
            f.write(res)
    
        return {
          
          "code": 1, "msg": "上传成功:{}".format(file.filename)}
    
    if __name__ == '__main__':
        import uvicorn
        uvicorn.run(app="main:app", host="0.0.0.0", port=2333)
    

Extension: upload files

  • Way 1:

    import requests
    import json
    
    if __name__ == '__main__':
        # 上传一张图
        file_path = r'E:\工具测试数据\封面上传测试\img\1825513ec0b.png'
        url = "http://127.0.0.1:2333/file_upload"
    
        data = {
          
          "file": open(file_path, 'rb')}
        res = requests.post(url=url, files=data, verify=False)
        print(json.loads(res.content))
        # {'code': 1, 'msg': '上传成功:7f63f6711f5f57d9.jpg'}
    
  • Way 2:

    import requests
    import json
    import os
    from urllib3 import encode_multipart_formdata
    
    if __name__ == '__main__':
        # 上传一张图
        file_path = r'E:\工具测试数据\封面上传测试\img\1825513ec0b.png'
        url = "http://127.0.0.1:2333/file_upload"
    
        with open(file_path, 'rb') as f:
            file_name = os.path.split(file_path)[-1]
            file = {
          
          "file": (file_name, f.read())}
            encode_data = encode_multipart_formdata(file)
            data = encode_data[0]
            content_type = encode_data[1]
            headers = {
          
          
                'Content-Type': content_type
            }
            res = requests.post(url, headers=headers, data=data)
            print(json.loads(res.content))
            # {'code': 1, 'msg': '上传成功:1825513ec0b.png'}
    

Request (request object)

  • request 对象

    FastAPI can use the fastapi.Request model in the route processing function to obtain request details, such as headers, query parameters, etc.

    from fastapi import FastAPI, Request
    
    @app.get("/user-agent/")
    def read_user_agent(request: Request):
        # 获取请求头
        headers = request.headers
        user_agent = headers.get("user-agent")
        return {
          
          "user_agent": user_agent}
    
  • Information in request headers

    FastAPI can use the fastapi.Header model in the routing processing function to obtain the information in the request header, such as user_agent, etc.

    from fastapi import FastAPI, Header
    
    @app.get("/headers/")
    def read_headers(user_agent: str = Header(None)):
        return {
          
          "User-Agent": user_agent}
    

safety

  • FastAPI provides multiple security mechanisms to protect web applications from common security risks and attacks. The following are some common security mechanisms in FastAPI:
    • Authentication: FastAPI supports multiple authentication methods, such as OAuth2, JWT (JSON Web Tokens), basic authentication, etc. You can use Depends to authenticate the user in the route, and only authenticated users can access protected resources.
    • Authorization: Once a user is authenticated, FastAPI also allows the implementation of an authorization mechanism to determine whether the user has permission to access a specific resource. This can be achieved through custom dependencies or decorators.
    • CORS (Cross-Origin Resource Sharing): CORS is a security mechanism used to control cross-domain requests. FastAPI allows configuring CORS policies to ensure that only requests from specific origins can access your API.
    • CSRF (Cross-site Request Forgery) Defense: FastAPI provides built-in CSRF protection to prevent CSRF attacks and protect your users from malicious websites.
    • Security Headers: FastAPI automatically adds some security headers to the response to protect applications from some common network attacks, such as clickjacking, XSS ( cross-site scripting attacks), etc.
    • Password Hashing and Storage: FastAPI encourages the use of password hashes to store user passwords to protect user privacy. Password hashing and verification can be done using the built-in Passlib library.
    • Request verification and input verification: FastAPI has built-in request verification and input verification mechanisms to filter and verify incoming data to prevent bad input and malicious data attacks.
    • Logging and Auditing: FastAPI allows logging of application activity for auditing and analysis in the event of a security incident.
    • HTTPS support: FastAPI supports encrypted connections over HTTPS to ensure the security of data during transmission.

expand

Visit Fast API interface documentation

  • Swagger UI Provided api 文档

    ip:port/docs (default 127.0.0.1:8000/docs)

  • ReDoc Provided api 文档

    ip:port/docs (default 127.0.0.1:8000/redoc)


Basic directory structure of the FastAPI project

my_project/
├── app/                                
│   ├── apis/
│   │   ├── __init__.py
│   │   ├── auth.py
│   │   ├── items.py
│   │   └── users.py
│   ├── core/
│   │   ├── __init__.py
│   │   ├── config.py
│   │   ├── security.py
│   │   └── sqlalchemy.py
│   ├── db/
│   │   ├── __init__.py
│   │   └── base.py
│   ├── main.py
│   └── models/
│       ├── __init__.py
│       ├── item.py
│       └── user.py
├── docker-compose.yml
├── Dockerfile
├── README.md
└── requirements.txt
  • app/: used to store the main code of the application. Contains API definition, business logic, database connection, etc.
  • app/apis/: Directory for API routing and business logic implementation.
  • app/core/: Implementation of core functions such as configuration, authentication, and database connection.
  • app/db/: The definition of the database model and database-related code.
  • app/models/: ORM model definition, realizing the mapping of business logic and database operations.
  • app/main.py: The startup file of the FastAPI application, including application initialization, route registration, etc.
  • docker-compose.yml: Docker-Compose configuration file
  • Dockerfile: the build file for the application Docker image
  • README.md: project documentation
  • requirements.txt: project dependency list

In addition, other directories and files can be added according to project needs, such as static file directories, test directories, document directories, etc. However, no matter how you organize the FastAPI project structure, you need to ensure that the code is clear and easy to maintain.

Guess you like

Origin blog.csdn.net/footless_bird/article/details/134369505