概述
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="chise123@live.com")
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 : chise123@live.com
@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
實現效果