Flask-Marshmallow:如何在PUT请求时将所有字段设为可选
解决PUT请求时Marshmallow Schema字段可选的问题
我完全懂你的困扰——创建用户时必须严格校验必填字段,但更新时只需要处理传入的字段,没必要强制要求传所有必填项,不然前端每次更新都要重复提交所有字段,太繁琐了。下面给你几个实用的解决方案,从简洁到灵活都有:
方案一:用webargs的PartialSchema(最省心)
webargs本身就提供了PartialSchema工具,能直接把你的Schema所有字段变成可选状态,不用修改原Schema的定义,直接在PUT方法的装饰器里用就行:
from webargs.fields import PartialSchema class UserView(FlaskView): trailing_slash = False model = User schema = user_schema # POST方法保持原有逻辑,校验必填字段 @use_kwargs(schema.fields) def post(self, **kwargs): # 原有代码... # PUT方法用PartialSchema包装原Schema,让所有字段可选 @use_kwargs(PartialSchema(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})
这个方案的好处是零侵入原Schema,完美区分POST和PUT的校验规则,代码改动最小。
方案二:创建专门的更新Schema子类
如果后续更新和创建的校验规则差异变大(比如更新时不允许修改id或creation_date,或者有额外的校验逻辑),可以创建一个继承自原Schema的子类,重设字段的required属性:
class UserUpdateSchema(UserSchema): class Meta(UserSchema.Meta): pass # 把需要变成可选的字段的required设为False name = fields.Str(required=False, allow_none=False) email = fields.Email(required=False, allow_none=False) # 实例化更新用的Schema user_update_schema = UserUpdateSchema()
然后在PUT方法里用这个新Schema的fields:
@use_kwargs(user_update_schema.fields) def put(self, id, **kwargs): # 原有代码...
这种方式更清晰,适合校验规则复杂的场景,不同请求用不同的Schema,逻辑一目了然。
对你之前修改方案的点评
你之前尝试给字段加missing=None,然后在代码里判断kwargs[d] is not missing and kwargs[d] is not None,这个方法确实能运行,但有两个小问题:
- 手动给每个必填字段加
missing=None太繁琐,如果模型字段多的话工作量大; - 你的模型里
name和email是nullable=False,所以其实不允许设为None,加missing=None容易造成逻辑混淆。
所以更推荐前面两种方案,更符合RESTful API的设计习惯。
内容的提问来源于stack exchange,提问作者RRR
相关产品推荐
相关产品推荐

