You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

更新命令空字段问题:无法区分默认None与主动设置的None

解决Update命令中None值来源判断的问题

在更新操作中,无法区分命令里的None是用户主动传入的,还是命令数据类的默认值,会导致错误覆盖或遗漏更新。以下是两种可行的解决方法:

方案一:使用特殊标记区分未设置字段

定义一个独一无二的特殊对象作为命令字段的默认值,替代原来的None。这样就能通过判断字段是否等于该标记,来区分是用户未传入字段,还是主动传入了None。

代码修改示例:

  1. 定义特殊标记:
# 可放在项目通用工具模块中
UNSET = object()
  1. 修改命令类:
# 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
  1. 处理函数中判断字段来源:
# 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()

方案二:记录用户实际传入的字段集合

在命令中新增一个集合字段,专门记录用户本次请求中实际传入的字段名。这样在处理函数中,只需检查字段名是否在该集合内,就能判断是否是用户主动设置的值。

代码修改示例:

  1. 修改命令类:
# 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)
  1. 在视图中传递实际传入的字段:
# 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)
  1. 处理函数中判断字段来源:
# 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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.25 02:24:10