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

实现效果

装饰之后大概就是这样的:
在这里插入图片描述

之后会逐渐增加新的功能,并优化代码。
目前有如下问题尚未解决:

  • db的传递问题,目前传递的db无法实现有效的关闭,会一直使用(也不知道时好时坏。。。)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值