fastapi之根據model生成schema和router

概述

fastapi沒有對應的admin,所以在需要配置後端的時候,會比較麻煩,每個接口都需要自己手動寫。
但是很多時候我們可能需要一個比較標準的東西,比如…一個裝飾器
通過裝飾器裝飾model就可以自動註冊路由,自動生成對應的標準方法,再根據更多的一些自定義配置,甚至不需要自己手動寫schema,然後不需要自己單獨寫路由相關的東西。(相當於給sqlalchemy的model增加django的model的部分功能)

原理

通過type動態生成對應的model。再自動註冊到服務器

使用說明

使用方法如下:

#創建model的時候,get_basemodel裝飾系統
@get_basemodel
class User(Base):
    __tablename__='users'
    id = Column(Integer, primary_key=True, index=True)
    email = Column(String(64), unique=True, index=True,default="[email protected]")
    hashed_password = Column(String(64))
    is_active = Column(Boolean, default=True)
    items = relationship("Item", back_populates="owner")

在main裏面的router註冊:

# user是model,app是寫入系統,
User.__model__.write2route('/user',app,User,get_db = SessionLocal())

這是一個demo,做技術驗證用,之後會逐步完善該功能,

裝飾器代碼

這裏只是有一個list的方法(對應methods的get)

# -*- encoding: utf-8 -*-
"""
@File    : test_selializers.py
@Time    : 2020/4/1 1:03
@Author  : chise
@Email   : [email protected]
@Software: PyCharm
@info    :嘗試將model轉爲basemodel的類,實現操作
"""
from pydantic import BaseModel, Field
from typing import NewType

from sqlalchemy import Integer, Table

UserId = NewType('UserId', int)
# admin_basemodel = []
from fastapi import APIRouter


class RouterBaseModel(BaseModel):
    """這個類主要是給生成的schema增加操作"""

    @staticmethod
    def list(model, db):  # 對應get方法
        """methods=get,讀取列表"""

        def res():
            return db.query(model).all()
            # print(model.__table__.select())

        return res

    def write2route(self, ul, route: APIRouter, model, get_db):
        """註冊到路由"""
        route.get(ul)(self.list(model, get_db))

    class Config:
        orm_mode = True


def get_basemodel(cls):
    """通過讀取model的信息,創建schema"""
    model_name = cls.__name__
    # mappings爲從model獲取的相關配置
    __mappings__ = {}  # {'name':{'field':Field,'type':type,}}

    for filed in cls.__table__.c:
        filed_name = str(filed).split('.')[-1]

        if filed.default:
            default_value = filed.default
        elif filed.nullable:
            default_value = ...
        else:
            default_value = None
        # 生成的結構: id:int=Field(...,)大概這樣的結構
        res_field = Field(default_value, description=filed.description)  # Field參數
        if isinstance(filed.type, Integer):
            tp = NewType(filed_name, int)
        else:
            tp = NewType(filed_name, str)
        __mappings__[filed_name] = {'tp': tp, 'Field': res_field}
    res = type(model_name, (RouterBaseModel,), __mappings__)
    # 將schema綁定到model
    cls.__model__ = res()
    return cls

實現效果

裝飾之後大概就是這樣的:
在這裏插入圖片描述

之後會逐漸增加新的功能,並優化代碼。
目前有如下問題尚未解決:

  • db的傳遞問題,目前傳遞的db無法實現有效的關閉,會一直使用(也不知道時好時壞。。。)
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章