flask-marshmallow:如何仅在方法为 PUT 时将所有字段标记为可选
flask-marshmallow: how to mark all fields as optional only when the method is PUT
我正在制作烧瓶 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 将它们标记为必需的。我的 get
、index
、delete
和 post
方法都非常有效。但出于一个原因,我包括了 post:
例如,当我尝试 post 一个没有名字的新用户时,会出现 422 http 代码,因为 name
字段是必需的,这是我想要的,而且做得很好。
但是当使用 put
请求编辑字段时,我希望我的模式中的所有内容都变成可选的。现在如果我想更新用户,我不仅必须提供 ID ,而且还必须提供所有其他信息默认情况下需要,即使我根本没有更改它们。
简而言之,如何在方法为"put"时将所有字段标记为"optional"?
编辑: 就像@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:
既然您想在 put
期间将字段设置为可选,那么如何为字段设置 missing
属性。来自 doc:
missing is used for deserialization if the field is not found in the
input data
我认为 missing
和 allow_none
的组合(当 missing=None
时默认为 True
),正如此处指出的:https://github.com/marshmallow-code/marshmallow/blob/dev/src/marshmallow/fields.py#L89 应该适用于你
我正在制作烧瓶 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 将它们标记为必需的。我的 get
、index
、delete
和 post
方法都非常有效。但出于一个原因,我包括了 post:
例如,当我尝试 post 一个没有名字的新用户时,会出现 422 http 代码,因为 name
字段是必需的,这是我想要的,而且做得很好。
但是当使用 put
请求编辑字段时,我希望我的模式中的所有内容都变成可选的。现在如果我想更新用户,我不仅必须提供 ID ,而且还必须提供所有其他信息默认情况下需要,即使我根本没有更改它们。
简而言之,如何在方法为"put"时将所有字段标记为"optional"?
编辑: 就像@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:
既然您想在 put
期间将字段设置为可选,那么如何为字段设置 missing
属性。来自 doc:
missing is used for deserialization if the field is not found in the input data
我认为 missing
和 allow_none
的组合(当 missing=None
时默认为 True
),正如此处指出的:https://github.com/marshmallow-code/marshmallow/blob/dev/src/marshmallow/fields.py#L89 应该适用于你