在Strawberry中如何配置更新突变的输入字段:可选且非空
在Strawberry中如何配置更新突变的输入字段:可选且非空
我完全懂你的困扰——你想要name字段在更新突变里是可选的(可以不传),但一旦传值就必须是有效的字符串,不能是null;而description则允许不传、传字符串或者传null。之前的写法要么让name能被设为null,要么把它变成必填项,确实有点棘手。
这里有个精准的解决方案,利用Strawberry的字段配置来区分Python类型提示和GraphQL schema约束:
from typing import Annotated, Optional import strawberry @strawberry.input class UserUpdateInput: # name:可选(不传则为UNSET),但传值时必须是字符串,不能为null name: Annotated[str, strawberry.field(nullable=False)] = strawberry.UNSET # description:可选,支持传字符串、null或者不传 description: Optional[str] = strawberry.UNSET
为什么这样写能解决问题?
- 对于
name字段:Annotated[str, strawberry.field(nullable=False)]告诉Strawberry,在GraphQL层面这个字段不接受null值;而strawberry.UNSET默认值让它成为可选字段——客户端可以选择不传,但传的话必须是字符串,完美匹配你数据库的非空约束。
- 对于
description字段:Optional[str]让Strawberry自动生成可空的GraphQL类型,加上strawberry.UNSET默认值,既允许不传,也允许传字符串或null,完全满足需求。
对应的GraphQL Schema
配置后生成的GraphQL输入类型如下:
input UserUpdateInput { name: String description: String }
这里的name是非空可选字段——客户端可以不传,但传值必须是字符串;description是可空可选字段,支持传null。
验证你的Mutation场景
- ✅ 允许的突变(同时更新name和description):
mutation Update { updateUser(id:1, userUpdateInput: {name:"tom",description:"too old for this s..."}) { id } }
- ✅ 允许的突变(将description设为null):
mutation Update { updateUser(id:1, userUpdateInput: {description:null}) { id } }
- ❌ 不允许的突变(尝试将name设为null):GraphQL会在请求阶段直接报错,拒绝无效输入,不会走到后端逻辑。
后端解析逻辑示例
在突变解析器里,只需要处理非UNSET的字段即可:
@strawberry.type class Mutation: @strawberry.mutation def update_user(self, id: int, user_update_input: UserUpdateInput) -> User: # 从数据库获取目标用户 user = get_user_from_database(id) # 仅当name被显式传入时才更新 if user_update_input.name is not strawberry.UNSET: user.name = user_update_input.name # 处理description:无论是传入字符串还是null,只要不是UNSET就更新 if user_update_input.description is not strawberry.UNSET: user.description = user_update_input.description # 保存到数据库 save_user_to_database(user) return user
备注:内容来源于stack exchange,提问作者Matthew Wilcoxson
相关产品推荐
相关产品推荐

