【问题标题】:API design using Flask, combining SQL Alchemy and Marshmallow使用 Flask 进行 API 设计,结合 SQL Alchemy 和 Marshmallow
【发布时间】:2020-04-10 17:18:47
【问题描述】:

我正在创建一个简单的 CRUD 应用程序。我正在使用 Flask,我决定使用 SQLAlchemy 作为 ORM,并使用 Marshmallow 来验证有效负载。

我目前的问题是尽量减少我需要编写的复制量。

在这种情况下,我们只是在处理帖子。

创建

models.py

class Post(Base):
    __tablename__ = 'posts'

    id = Column(UUID(as_uuid=True), primary_key=True)
    user_id = Column(UUID(as_uuid=True), ForeignKey('users.id'))
    title = Column(String(length=50)) 

schemas.py

class CreatePostSchema(Schema):
    title = fields.Str(required=True)

我不需要iduser_id,因为它们将由后端创建/找到,但所有其他字段都是必需的。

我正在使用 BluePrints,与帖子创建相关的路由/端点之一将具有 post() 方法。

我可以创建装饰器以首先确保架构正确,获取用户并将其传递给 post 方法:

@auth_required()
@validate_schema(CreatePostSchema)
def post(request, user_id, cleaned_schema):
    create_post(cleaned_schema)
    return 200

现在,我可以编写 create_post() 函数而无需硬编码键,例如:

def create_post(user_id, **clean_data)
    post = models.Post(**clean_data)
    post.user_id = user_id

但这是好的做法吗?或者我应该明确说明如下键:

def create_post(user_id, title)
    post = models.Post(title=title)
    post.user_id = user_id
    post.id = uuid4()
    return post

然后我还有一个问题,在哪个阶段进行验证。验证应该在post() 方法之前进行,还是在创建帖子期间进行?例如,我可以这样做:

def create_post(user_id, **data):
    clean_data = CreatePostSchema.load(**data)
    post = models.Post(**clean_data)
    session.add(post)
    session.commit()
    return

这样我可以删除额外的@has_schema() 装饰器。

更新

更新是一种无需重复键即可编写的不同野兽。假设我们只有 1 个字段和 EditPostSchema = CreatePostSchema。实际上,我会拥有更多,例如创建日期、更新日期、描述等

clean_data = EditPostSchema.load(**data)
id = clean_data.pop('id')
update_post(id, clean_data)

def update_post(id, **clean_data):
    session.query(Post).get(id).update(**clean_data, synchronize_session=False)
    return

所以本质上,我认为Schemas 应该已经解释了我需要用于 CRUD 的字段,所以我不需要重复它们。我说的对吗?

【问题讨论】:

    标签: python sqlalchemy marshmallow


    【解决方案1】:

    您可以使用 webargs 使用棉花糖模式验证输入数据。

    如果你想避免代码重复,你也可以尝试marshmallow-sqlalchemy从模型生成API模式。

    如果 API 与模型足够接近,您可以通过在 POST 中传递输入数据来创建对象:

    post = models.Post(**data)
    

    更新确实不同。有些人只是用传入的数据更新对象,但这可能不适用于所有情况,因为数据中的空字段会导致对象中的字段被删除。

    您可以对要更新的字段进行硬编码。

    在我的一个应用程序中,我创建了一个将架构作为参数的函数,并使用它来了解预期哪些字段并使用传入数据更新对象,包括删除该数据中缺少的字段。

    【讨论】:

      猜你喜欢
      • 2018-07-14
      • 1970-01-01
      • 2017-03-26
      • 2017-06-08
      • 1970-01-01
      • 2014-08-26
      • 2016-05-29
      • 2020-03-20
      • 1970-01-01
      相关资源
      最近更新 更多