概述
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無法實現有效的關閉,會一直使用(也不知道時好時壞。。。)