zoukankan      html  css  js  c++  java
  • FastAPI(21)- 多个模型的代码演进

    前言

    在一个完整的应用程序中,通常会有很多个相关模型,比如

    • 请求模型需要有 password
    • 响应模型不应该有 password
    • 数据库模型可能需要一个 hash 加密过的 password

    多个模型的栗子

    需求

    • 注册功能
    • 请求输入密码
    • 响应不需要输出密码
    • 数据库存储加密后的密码

    实际代码

    #!usr/bin/env python
    # -*- coding:utf-8 _*-
    """
    # author: 小菠萝测试笔记
    # blog:  https://www.cnblogs.com/poloyy/
    # time: 2021/9/22 8:28 上午
    # file: 19_extra models.py
    """
    
    import uvicorn
    from fastapi import FastAPI
    from typing import Optional
    from pydantic import BaseModel, EmailStr
    
    app = FastAPI()
    
    
    # 请求模型
    class UserIn(BaseModel):
        username: str
        password: str
        email: EmailStr
        full_name: Optional[str] = None
    
    
    # 响应模型
    class UserOut(BaseModel):
        username: str
        email: EmailStr
        full_name: Optional[str] = None
    
    
    # 数据库模型
    class UserInDB(BaseModel):
        username: str
        hashed_password: str
        email: EmailStr
        full_name: Optional[str] = None
    
    
    # 加密算法
    def fake_password_hasher(password: str) -> str:
        return "supersecret" + password
    
    
    # 数据库存储
    def fake_save_user(user: UserIn):
        # 取出用户的密码进行加密
        hash_password = fake_password_hasher(user.password)
        # 转换为数据库模型
        userInDB = UserInDB(**user.dict(), hashed_password=hash_password)
        # 返回数据
        return userInDB
    
    
    @app.post("/user", response_model=UserOut)
    async def create_user(user: UserIn):
        # 创建用户,落库
        user_saved = fake_save_user(user)
        # 返回存储后的用户信息
        return user_saved
    
    if __name__ == "__main__":
        uvicorn.run(app="19_extra_models:app", host="127.0.0.1", port=8080, reload=True, debug=True)

    .dict()

    是 Pydantic 提供的方法,将模型的实例对象转换为 dict 

    Pydantic 入门篇

    **user.dict()

    先将 user 转成 dict,然后解包

    Python 解包教程

    减少代码重复

    核心思想

    • 减少代码重复是 FastAPI 的核心思想之一。
    • 因为代码重复增加了错误、安全问题、代码同步问题(当在一个地方更新而不是在其他地方更新时)等的可能性

    上面代码存在的问题

    三个模型都共享大量数据

    利用 Python 继承的思想进行改造

    • 声明一个 UserBase 模型,作为其他模型的基础
    • 然后创建该模型的子类来继承其属性(类型声明、验证等),所有数据转换、验证、文档等仍然能正常使用
    • 这样,不同模型之间的差异(使用明文密码、使用哈希密码、不使用密码)也很容易识别出来
    #!usr/bin/env python
    # -*- coding:utf-8 _*-
    """
    # author: 小菠萝测试笔记
    # blog:  https://www.cnblogs.com/poloyy/
    # time: 2021/9/22 8:28 上午
    # file: 19_extra models.py
    """
    
    import uvicorn
    from fastapi import FastAPI
    from typing import Optional
    from pydantic import BaseModel, EmailStr
    
    app = FastAPI()
    
    
    # 基类模型
    class UserBase(BaseModel):
        username: str
        email: EmailStr
        full_name: Optional[str] = None
    
    
    # 请求模型
    class UserIn(UserBase):
        password: str
    
    
    # 响应模型
    class UserOut(UserBase):
        pass
    
    
    # 数据库模型
    class UserInDB(UserBase):
        hashed_password: str
    
    
    # 加密算法
    def fake_password_hasher(password: str) -> str:
        return "supersecret" + password
    
    
    # 数据库存储
    def fake_save_user(user: UserIn):
        # 取出用户的密码进行加密
        hash_password = fake_password_hasher(user.password)
        # 转换为数据库模型
        userInDB = UserInDB(**user.dict(), hashed_password=hash_password)
        # 返回数据
        return userInDB
    
    
    @app.post("/user", response_model=UserOut)
    async def create_user(user: UserIn):
        # 创建用户,落库
        user_saved = fake_save_user(user)
        # 返回存储后的用户信息
        return user_saved
    
    
    if __name__ == "__main__":
        uvicorn.run(app="19_extra models:app", host="127.0.0.1", port=8080, reload=True, debug=True)
  • 相关阅读:
    PMP笔记:行政收尾工作
    PMP 笔记:WBS 词典 (含范例)
    PMP 笔记:WBS 实战 (例子)
    名义小组和德尔菲技术使用与区别
    焦点小组、名义小组和引导式会议的定义与区别
    工作分解结构WBS、组织分解结构OBS、资源分解结构 定义和区别(含例子)
    kettle里的参数和变量
    kettle生成100个随机数,并统计小于等于50和大于50个数
    使用kettle制作拉链表
    MySQL字符串转日期
  • 原文地址:https://www.cnblogs.com/poloyy/p/15318146.html
Copyright © 2011-2022 走看看