使用数据库数据模型生成 SQLAlchemy 模型、架构和 JSON 响应

2024-05-06

将 Flask 和 SQLAlchemy 用于 Python Web 应用程序,我的目标是创建一个系统,在其中我可以:

  1. 从现有 PostgreSQL 数据库导入数据模型,并将它们映射到相应 SQLAlchemy 模型中的字段
  2. 使用这些 SQLAlchemy 模型自动生成架构。然后,该模式将用于对用户提交的数据执行数据验证。(我目前正在尝试使用 Marshmallow,但我愿意接受其他建议)。
  3. 使用步骤 2 中生成的架构执行 JSON 响应格式化。(我目前正在尝试根据 JsonAPI 的架构格式化我的响应 - 如果需要,这可以更改,但我更喜欢它)。

所有这些都将打包在一个层中,在编写 API 时应允许简单的数据访问、验证和响应格式化,希望无需手动定义超出数据库中已存在的定义的数据模型或模式。这引出了我的问题:

我可以利用现有框架来完成我想要完成的所有事情吗?我并不期望有一个库可以完成所有工作,但我希望能够利用多个现有框架。然而,我遇到了直接冲突,特别是在步骤 2 和 3 中。到目前为止我一直尝试使用的堆栈如下:

  • Flask(我的网络框架)
  • SQLAlchemy(用于通过反射访问我的数据,见下文)
  • Flask-Marshmallow(生成数据验证模式)
  • Marshmallow-JsonAPI(根据 JsonAPI 规范格式化 JSON 响应)

我有第 1 步的解决方案:SQLAlchemy 的反射。这使我能够读取现有数据库中的表并将它们映射到 SQLAlchemy 模型。这效果很好。

步骤 2 和 3 的组合是它变得模糊的地方 - 我正在尝试使用 Flask-Marshmallow 和 Marshmallow-JsonAPI。烧瓶棉花糖有模型架构类 https://flask-marshmallow.readthedocs.io/en/latest/#flask_marshmallow.sqla.ModelSchema,它允许您通过向其传递现有的 SQLAlchemy 模型来生成架构。我可以将步骤 1 中生成的 SQLAlchemy 模型传递给它,满足步骤 2 的标准。至于 Marshmallow-JsonAPI,它的功能使您可以为模型定义架构,并且它将自动创建符合 JSONAPI 的响应,满足我的步骤 3 的标准。我可以单独获取这些框架中的每一个来完成我需要的操作。

不幸的是,由于我的架构必须继承 Flask-Marshmallow 和 Marshmallow-JSONAPI 中的架构类,因此我遇到了问题。我的“虚拟”类模型如下所示:

import flask
from marshmallow_jsonapi import Schema, fields
from sqlalchemy.ext.declarative import DeferredReflection
from flask_marshmallow import Marshmallow
from flask_sqlalchemy import SQLAlchemy

app = flask.Flask(__name__)
DB = SQLAlchemy()
DB.init_app(app)
MA = Marshmallow(app)
DeferredReflection.prepare(DB.get_engine(app))

class Dummy(DeferredReflection, DB.Model):
    __tablename__ = "dummy"  # This model will be reflected from the Dummy table


class DummySchema(MA.ModelSchema, Schema):  # The problem line
    class Meta:
        model = Dummy  # Create schema for the Dummy model

在尝试启动我的 API 时,我收到如下奇怪的错误:

api_1        | [2017-01-05 23:16:13,379] ERROR in app: Exception on /api/dummy [POST]
api_1        | Traceback (most recent call last):
api_1        |   File "/usr/local/lib/python3.5/site-packages/flask/app.py", line 1612, in full_dispatch_request
api_1        |     rv = self.dispatch_request()
api_1        |   File "/usr/local/lib/python3.5/site-packages/flask/app.py", line 1598, in dispatch_request
api_1        |     return self.view_functions[rule.endpoint](**req.view_args)
api_1        |   File "/usr/local/lib/python3.5/site-packages/flask_restful/__init__.py", line 477, in wrapper
api_1        |     resp = resource(*args, **kwargs)
api_1        |   File "/usr/local/lib/python3.5/site-packages/flask/views.py", line 84, in view
api_1        |     return self.dispatch_request(*args, **kwargs)
api_1        |   File "/usr/local/lib/python3.5/site-packages/flask_restful/__init__.py", line 587, in dispatch_request
api_1        |     resp = meth(*args, **kwargs)
api_1        |   File "/dummyproj/api/src/dummyproj/api/v1/dummy_resource.py", line 34, in post
api_1        |     dummy_schema = dummy.DummySchema()
api_1        |   File "/usr/local/lib/python3.5/site-packages/marshmallow_sqlalchemy/schema.py", line 143, in __init__
api_1        |     super(ModelSchema, self).__init__(*args, **kwargs)
api_1        |   File "/usr/local/lib/python3.5/site-packages/marshmallow_jsonapi/schema.py", line 81, in __init__
api_1        |     super(Schema, self).__init__(*args, **kwargs)
api_1        |   File "/usr/local/lib/python3.5/site-packages/marshmallow/schema.py", line 358, in __init__
api_1        |     self._update_fields(many=many)
api_1        |   File "/usr/local/lib/python3.5/site-packages/marshmallow/schema.py", line 750, in _update_fields
api_1        |     self.__set_field_attrs(ret)
api_1        |   File "/usr/local/lib/python3.5/site-packages/marshmallow/schema.py", line 772, in __set_field_attrs
api_1        |     self.on_bind_field(field_name, field_obj)
api_1        |   File "/usr/local/lib/python3.5/site-packages/marshmallow_jsonapi/schema.py", line 164, in on_bind_field
api_1        |     field_obj.load_from = self.inflect(field_name)
api_1        |   File "/usr/local/lib/python3.5/site-packages/marshmallow_jsonapi/schema.py", line 190, in inflect
api_1        |     return self.opts.inflect(text) if self.opts.inflect else text
api_1        | AttributeError: 'SchemaOpts' object has no attribute 'inflect'

看来,由于我的 Schema 类继承自两个不同的超类,因此会导致问题。我希望这两个棉花糖库非常兼容,但似乎确实有一个issue https://github.com/marshmallow-code/marshmallow-jsonapi/issues/3有了这个。

所有这一切的结果是我不太确定下一步该尝试什么。我并不是真的期待任何有关 Marshmallow 框架的具体建议,更多只是想展示我的思路。是否有围绕这种设计的最佳实践,或者我是否试图一次解决太多问题?

(对于 Python 和 SO 来说都是新的 - 如果有任何不清楚的地方,我们深表歉意)。


我成功组合了 marshmallow-jsonapi + marshmallow-sqlalchemy。这就是魔法:

import marshmallow
import marshmallow_jsonapi
import marshmallow_jsonapi.flask
import marshmallow_sqlalchemy

import myapp.database as db


def make_jsonapi_schema_class(model_class):
    class SchemaOpts(marshmallow_sqlalchemy.SQLAlchemyAutoSchemaOpts, marshmallow_jsonapi.SchemaOpts):
        pass

    class Schema(marshmallow_sqlalchemy.SQLAlchemyAutoSchema, marshmallow_jsonapi.flask.Schema):
        OPTIONS_CLASS = SchemaOpts

        @marshmallow.post_load
        def make_instance(self, data, **kwargs):
            # Return deserialized data as a dict, not a model instance
            return data

        # You can add default behavior here, for example
        # id = fields.Str(dump_only=True)

    # https://marshmallow-sqlalchemy.readthedocs.io/en/latest/recipes.html#automatically-generating-schemas-for-sqlalchemy-models
    class Meta:
        # Marshmallow-SQLAlchemy
        model = model_class
        sqla_session = db.session

        # Marshmallow-JSONAPI
        type_ = model_class.__name__.lower()
        self_view = type_ + '_detail'
        self_view_kwargs = {'id': '<id>'}
        self_view_many = type_ + '_list'

    schema_class = type(model_class.__name__ + 'Schema', (Schema,), {'Meta': Meta})
    return schema_class

然后你打电话

FooSchema = make_jsonapi_schema_class(Foo)

从 SQLAlchemy 声明性模型生成 Marshmallow 架构类。如果您想自定义它,您可以依次子类化该类。

(为了实现 REST API,我使用Flask-REST-JSONAPI https://flask-rest-jsonapi.readthedocs.io/,它构建在 Flask + SQLAlchemy + marshmallow-jsonapi 之上。)

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

使用数据库数据模型生成 SQLAlchemy 模型、架构和 JSON 响应 的相关文章

  • docker-compose:容器之间的 Redis 连接被拒绝

    我正在尝试设置一个 docker compose 文件 该文件旨在替换运行多个进程 RQ 工作线程 RQ 仪表板和 Flask 应用程序 的单个 Docker 容器解决方案导师 http supervisord org 主机系统是 Debi
  • 硒网格监听节点端口而不是集线器端口

    对于我的测试 我在不同的端口上本地运行网格和节点 java jar usr bin selenium server jar port 4444 role hub java jar usr bin selenium server jar ro
  • 使用 OpenCV 进行图像模糊检测

    我正在研究图像的模糊检测 我已经用过拉普拉斯方法的方差在 OpenCV 中 img cv2 imread imgPath gray cv2 cvtColor img cv2 COLOR BGR2GRAY value cv2 Laplacia
  • gcloud app deploy:此部署有太多文件

    当我尝试通过 gcloud 部署我的 GAE 应用程序时 出现以下错误 Updating service default failed ERROR gcloud app deploy Error Response 400 This depl
  • 为什么 np.linalg.norm(..., axis=1) 比写出向量范数公式慢?

    标准化矩阵的行X对于单位长度 我通常使用 X np linalg norm X axis 1 keepdims True 在尝试优化算法的此操作时 我非常惊讶地发现在我的机器上写出标准化的速度大约快了 40 X np sqrt X 0 2
  • 点击后 Dash DropDown 关闭

    我不希望下拉菜单在选择值后关闭 我希望它在我的页面上保持打开状态 我正在使用 dcc Dropdown dcc Dropdown id job type options self options placeholder Select one
  • Python/Scipy 2D 插值(非均匀数据)

    这是我上一篇文章的后续问题 Python Scipy 插值 地图坐标 https stackoverflow com questions 5124126 python scipy interpolation map coordinates
  • Python 将 0 计算为 False

    在 Python 控制台中 gt gt gt a 0 gt gt gt if a print L gt gt gt a 1 gt gt gt if a print L L gt gt gt a 2 gt gt gt if a print L
  • 如何在Python中比较列表列表中的元素以及比较列表列表中的键?

    我有以下顺序 seq ATG ATG ATG ATG GAC GAT GAA CCT GCC GCG GCA GCT 这是一个字典键 用于存储每个密码子的氨基酸值 三联碱基 例如ATG GCT etc aminoacid TTT F TTC
  • 并行磁盘 I/O

    我有几个想要阅读的日志文件 不失一般性 假设日志文件处理如下 def process infilepath answer 0 with open infilepath as infile for line in infile if line
  • Python:使用Excel CSV文件仅读取某些列和行

    虽然我可以读取 csv 文件而不是读取整个文件 但如何仅打印某些行和列 想象一下这是 Excel A B C D E State Heart Disease Rate Stroke Death Rate HIV Diagnosis Rate
  • Django - 从时间戳获取不同的日期

    我正在尝试按日期过滤用户 但直到我可以找到数据库中用户的第一个和最后一个日期为止 虽然我可以让我的脚本稍后过滤掉重复项 但我想从一开始就使用 Django 来完成此操作distinct因为它显着减少 我试过 User objects val
  • pygame.image.load 不工作

    我正在尝试为游戏创建世界地图 但是当我尝试将世界地图加载到屏幕上时 命令行告诉我无法执行此操作 这是代码 import sys import pygame from pygame locals import pygame init Surf
  • “gi.repository.Gtk”对象没有属性“gdk”

    我正在尝试使用 GTK 创建多线程 需要 Gtk gdk 但我收到有关没有 gdk 属性的错误 我正在使用带有 Raspbian 的 Raspberry Pi 这就是我导入 GTK 库的方式 try import pygtk pygtk r
  • PyQt 和 QSignalMapper/lambdas - 多个信号,单槽

    我在 PyQt 的菜单上有一个操作列表 每个操作对应我想要显示的每个不同的提要 所以我有一个 Y 将活动源设置为 Y Z 将其设置为 Z 等等 对于网络漫画阅读程序 我的菜单上都有 并且觉得自动化方法可能更好 而不是每次都打字 类似于将其添
  • 从 Python 访问 802.11 无线管理帧

    我想从 Linux 上的 Python 嗅探 802 11 管理 探测请求 帧 这可以从 Scapy 中实现 如下所示 coding utf 8 from scapy all import def proc p if p haslayer
  • centos上无法安装Pillow

    我上面有 centos 6 3 和 python 2 6 当我尝试通过 easy install 安装它时 出现以下错误 imaging c 76 20 error Python h No such file or directory In
  • Django 表单中的只读字段

    如何在 Django 表单中将字段设置为只读 我知道如何禁用某个字段 但这不是我想要的 任何帮助 将不胜感激 您可以使用可选的attrs定义时的参数Field 以机智 somefield forms CharField widget for
  • 写入文件的正确方法?

    我想知道这样做是否有什么区别 var1 open filename w write Hello world 并做 var1 open filename w var1 write Hello world var1 close 我发现没有必要
  • 我收到错误:rest_framework.request.WrappedAttributeError:'CSRFCheck'对象没有属性'process_request'

    urls py from django conf urls import url from django contrib import admin from django conf import settings from django c

随机推荐

  • SSIS 脚本编辑器抛出异常

    我有 SQL Server 2012 SSIS SSDT 和 Visual Studio 2010 我可以创建一个新的 SSIS 包并添加脚本任务 但如果我尝试打开该脚本任务的脚本编辑器 则会收到以下错误 TITLE Microsoft V
  • 使用 simple_form 条目输入空数组值

    我对 Rails 和 simple form 仍然很陌生 并且一直在尝试实现多重选择选项来为用户提供多个角色 当前输入看起来像这样 所以 这确实有效 但在数组的开头包含一个空值 secondary
  • Android Studio 中的多个光标会自动出现在每个匹配的文本处吗?

    我一直在使用多个光标ALT SHIFT 有时我需要大约 20 个光标 并且希望它们位于文本同一部分的开头 每次都这样做很乏味 这有捷径吗 就像想象文件中有 20 个文本 foo 的实例 那么我只想选择一个 理想情况下它应该自动为同一位置的所
  • 我可以在反向传播期间(有选择地)反转 Theano 梯度吗?

    我热衷于利用最近论文中提出的架构 通过反向传播进行无监督域适应 http arxiv org pdf 1409 7495 pdf 在 Lasagne Theano 框架中 这篇论文的有点不同寻常之处在于它包含了一个 梯度反转层 invert
  • C# 字典值引用类型 - 请解释为什么会发生这种情况

    我不明白 C 中以下 linqpad 查询的结果 评论应该解释我困惑的地方 void Main Dictionary
  • 结构中字符串的管理

    我知道字符串的长度是可变的 因此它们需要内存中的可变空间来存储 当我们在 a 中定义一个字符串项时struct the struct的大小的长度将是可变的 较旧的语言通过使用固定长度的字符串来管理此问题 但是 C 中没有办法定义固定长度的字
  • 如果在 addSubView 之后调用,UIButton 不会移动

    所以我想移动一个UIButton单击后 The addMoreFields单击按钮后调用该方法 addMoreFieldBtn是一个全球性的UIButton 当我点击它时什么也没有发生 奇怪的是 如果我注释掉addSubView代码然后按钮
  • 如何使用jquery通过ajax发送电子邮件地址

    var emailid email protected cdn cgi l email protection var data email emailid ajax type POST url sample php data data da
  • 尝试修复此错误:找不到映射的图像 UIPickerViewFrameLeft-162-Popover.png

    我正在尝试以编程方式创建 uiPickerView 并将其添加到视图中 而不使用界面生成器 不要误会我的意思 我喜欢 IB 但我想这样做的原因是因为我正在尝试构建一个对象 我可以快速插入该对象以使用 UIPopoverViewControl
  • chrome_options.binary_location() TypeError: 'str' 对象不可调用

    我希望每个人都好 我是 python 新手 我尝试运行这段代码 但我不明白问题是什么以及如何解决这个问题 我的代码是 from selenium import webdriver from time import sleep url raw
  • 用parsec解析递归数据

    import Data Attoparsec Text Lazy import Data Text Lazy Internal Text import Data Text Lazy pack data List a Nil Cons a L
  • 间接变量/参数引用(另一个属性/另一个变量中的名称)

    是否可以使用 XSL 访问名称存储在另一个变量 或参数 中的变量 或参数 如果没有 为什么 我是 xsl 的新手 来自其他语言 可以使用此功能 例如 bash ant 也许我在寻找这个问题的答案时就错了 但既然我在SO上没有找到它 我想应该
  • 使 div 更大并在悬停时向上动画更大的部分

    当用户将鼠标悬停在 div 上时 我试图将 div 向上设置动画 我可以对 div 进行动画处理 使其变大 但动画是向下发生的 我试图将 div 的底部保持在同一位置 并平滑地向上增加 div 的大小 请参阅 jsfiddle 这里 htt
  • Python - 重写 print()

    我正在使用 mod wsgi 想知道是否可以覆盖 print 命令 因为它没用 这样做是行不通的 print myPrintFunction 因为这是一个语法错误 Print 不是 Python 2 x 中的函数 因此这不能直接实现 但是
  • Javascript 设置输入字段的值

    因为虽然我无法设置 type text 的输入字段的值 以前 我总是使用这样的东西
  • 在heroku实例上安装PIL

    我创建了一个python flask托管在heroku上的应用程序 我很有趣PILpython 中的图像库 我无法安装PIL在heroku实例中 我尝试过以下几种方法 方法一 Added PIL 1 1 7 in requirements
  • 锁定 contenteditable="true" div 中的元素

    我有一个用于用户输入的 contenteditable div 当单击按钮时 它会显示替换某些单词的选项 首先 它删除所有 html 并创建可以替换单词的 span 元素 这些词的标记不同 我面临一些问题 当直接在跨度之前或之后单击并键入文
  • 将 Google Drive 目录中的所有文件恢复为旧版本

    最近 病毒加密了我的所有文件 不幸的是 谷歌备份和同步立即将文件的新版本 加密 上传到我的驱动器 我知道我可以将单个文件恢复到以前的版本 但我的驱动器上大约有 30 000 个文件 这意味着我无法手动恢复所有这些文件 我尝试使用 Apps
  • 如何编写Elasticsearch多个必须脚本查询?

    我想使用查询来比较多个字段 我有字段 1 到 4 我想搜索字段 1 大于字段 2 的数据 并且下面的查询工作正常 size 0 source field1 field2 field3 field4 sort query bool filte
  • 使用数据库数据模型生成 SQLAlchemy 模型、架构和 JSON 响应

    将 Flask 和 SQLAlchemy 用于 Python Web 应用程序 我的目标是创建一个系统 在其中我可以 从现有 PostgreSQL 数据库导入数据模型 并将它们映射到相应 SQLAlchemy 模型中的字段 使用这些 SQL