flask-marshmallow:仅当方法为 PUT 时如何将所有字段标记为可选

Posted

技术标签:

【中文标题】flask-marshmallow:仅当方法为 PUT 时如何将所有字段标记为可选【英文标题】:flask-marshmallow: how to mark all fields as optional only when the method is PUT 【发布时间】:2018-10-28 18:41:07 【问题描述】:

我正在制作一个烧瓶 restful api,我遇到的问题是 marshmallow-sqlalchemy 和 webargs

简而言之,这是我的 sqlalchemy 模型:

class User(Model):
    id = Column(String, primary_key=True)
    name = Column(String(64), nullable=False)
    email = Column(String(120), nullable=False)
    password = Column(String(128))
    creation_date = Column(DateTime, default=datetime.utcnow)

这是我的架构

class UserSchema(ModelSchema):
    class Meta:
        model = User
        strict = True
        sqla_session = db.session

user_schema = UserSchema()

以及我使用 flask-classful 和 webargs 的路线示例:

class UserView(FlaskView):
    trailing_slash = False
    model = User
    schema = user_schema

    @use_kwargs(schema.fields)
    def post(self, **kwargs):
        try:
            entity = self.model()

            for d in kwargs:
                if kwargs[d] is not missing:
                    entity.__setattr__(d, kwargs[d])

            db.session.add(entity)
            db.session.commit()
            o = self.schema.dump(entity).data
            return jsonify(''.format(self.model.__table__.name): o)

        except IntegrityError:
            return jsonify('message': ' exist in the database. choose another id'
                   .format(self.model.__table__.name)), 409


    @use_kwargs(schema.fields)
    def put(self, id, **kwargs):
        entity = self.model.query.filter_by(id=id).first_or_404()

        for d in kwargs:
            if kwargs[d] is not missing:
                entity.__setattr__(d, kwargs[d])

        db.session.commit()
        o = self.schema.dump(entity).data
        return jsonify(''.format(self.model.__table__.name): o)

UserView.register(app)

问题: 正如您在我的 sqlalchemy 模型中看到的那样,某些字段不可为空,因此我的 marshmallow schemda 将它们标记为必需。我的getindexdeletepost 方法都运行良好。但我包含帖子有一个原因:

例如,当我尝试发布一个没有姓名的新用户时,会引发一个 422 http 代码,因为 name 字段是必需的,这是我想要的,并且做得很好。

但是当编辑带有put 请求的字段时,我希望我的架构中的所有内容都成为可选的.. 现在如果我想更新用户,我不仅必须提供 id.. 而且默认情况下需要的所有其他信息甚至如果我根本没有改变它们。

简而言之,当方法为“put”时,如何将所有字段标记为“可选”?

编辑: 就像@Mekicha 提供的解决方案一样,我做了以下更改:

更改架构以使我的模型中的必填字段接受值无。像这样:

class UserSchema(ModelSchema):
    class Meta:
        model = User
        ...
    name = fields.Str(missing=None, required=True)
    email = fields.Email(missing=None, required=True)
    ...

从此更改我的 put 和 post 方法条件:

if kwargs[d] is not missing:

到这里:

if kwargs[d] is not missing and kwargs[d] is not None:

【问题讨论】:

看看partial loading上的文档 @Mekicha 我有点了解如何使用部分加载。但是如何在我的use_kwargs 中指定它,所以所有字段都是可选的?我尝试做 @use_kwargs(partial=True) 并将部分设置为一组字段,但它不起作用:( 请看我的回答,如果能帮到你 使用 partial=True 实例化架构,例如 @use_kwargs(UserSchema(partial=True)) @andho 这真的对你有用,还是“应该有用”?像 OP 一样,我有类似 @use_kwargs(user_schema.fields) 的东西,而不是 @use_kwargs(user_schema),我不记得为什么了。但是将user_schema = UserSchema(strict=True) 更改为user_schema = UserSchema(strict=True, partial=True) 并没有任何区别。我喜欢使用partial,而不是到处指定单个字段。 【参考方案1】:

由于您希望在put 期间将字段设为可选,那么如何为字段设置missing 属性。来自doc:

如果在 输入数据

我认为missingallow_none 的组合(missing=None 时默认为True)如下所示:https://github.com/marshmallow-code/marshmallow/blob/dev/src/marshmallow/fields.py#L89 应该适合你

【讨论】:

以上是关于flask-marshmallow:仅当方法为 PUT 时如何将所有字段标记为可选的主要内容,如果未能解决你的问题,请参考以下文章

仅当为输入参数找到某个元数据时,才在游标中加入 Oracle

如何计算一个矩阵的幂

视图函数未返回有效响应。烧瓶棉花糖,RestAPI [重复]

覆盖 Qt MouseEvent 但仅当类变量为 True 时

仅当特定输入为空时,如何禁用按钮?

仅当 pr 目标为 master 时才运行 GitHub 操作