更新命令空字段问题:无法区分默认None与主动设置的None
解决Update命令中None值来源判断的问题
在更新操作中,无法区分命令里的None是用户主动传入的,还是命令数据类的默认值,会导致错误覆盖或遗漏更新。以下是两种可行的解决方法:
方案一:使用特殊标记区分未设置字段
定义一个独一无二的特殊对象作为命令字段的默认值,替代原来的None。这样就能通过判断字段是否等于该标记,来区分是用户未传入字段,还是主动传入了None。
代码修改示例:
- 定义特殊标记:
# 可放在项目通用工具模块中 UNSET = object()
- 修改命令类:
# commands.py from dataclasses import dataclass from uuid import UUID from your_project.utils import UNSET @dataclass class UpdateCustomer(Command): id: UUID document: Optional[str] = UNSET name: Optional[str] = UNSET
- 处理函数中判断字段来源:
# handlers.py def update_customer( cmd: commands.UpdateCustomer, uow: AbstractCustomerUnitOfWork ) -> None: customer = uow.customers.get(cmd.id) # 仅当用户主动传入name(包括传入None)时才更新 if cmd.name is not UNSET: customer.name = cmd.name # 同理处理document字段 if cmd.document is not UNSET: customer.document = cmd.document uow.commit()
方案二:记录用户实际传入的字段集合
在命令中新增一个集合字段,专门记录用户本次请求中实际传入的字段名。这样在处理函数中,只需检查字段名是否在该集合内,就能判断是否是用户主动设置的值。
代码修改示例:
- 修改命令类:
# commands.py from dataclasses import dataclass, field from uuid import UUID from typing import Optional, Set @dataclass class UpdateCustomer(Command): id: UUID document: Optional[str] = None name: Optional[str] = None updated_fields: Set[str] = field(default_factory=set)
- 在视图中传递实际传入的字段:
# views.py def put(self, request, id): input_serializer = self.InputSerializer(data=request.data) input_serializer.is_valid(raise_exception=True) # 获取用户实际传入的所有字段名 updated_fields = set(input_serializer.validated_data.keys()) cmd = commands.UpdateCustomer( id=id, updated_fields=updated_fields, **input_serializer.validated_data ) bus = bootstrap.bootstrap() bus.handle(cmd) return Response(status=status.HTTP_204_NO_CONTENT)
- 处理函数中判断字段来源:
# handlers.py def update_customer( cmd: commands.UpdateCustomer, uow: AbstractCustomerUnitOfWork ) -> None: customer = uow.customers.get(cmd.id) # 检查name是否是用户主动传入的 if 'name' in cmd.updated_fields: customer.name = cmd.name # 检查document是否是用户主动传入的 if 'document' in cmd.updated_fields: customer.document = cmd.document uow.commit()
内容的提问来源于stack exchange,提问作者Perse
相关产品推荐
相关产品推荐

