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="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

  實現效果


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM