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

时间:2018-05-18 10:31:54

标签: python api flask marshmallow webargs

我正在制作一个安静的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提供的解决方案一样,我做了以下几个方面:

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

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:

1 个答案:

答案 0 :(得分:2)

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

  如果在中找不到该字段,则

missing用于反序列化   输入数据

我认为missingallow_none的组合(在True时默认为missing=None)如此指出:https://github.com/marshmallow-code/marshmallow/blob/dev/src/marshmallow/fields.py#L89应该对你有用< / p>