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

Django Ninja中如何让Schema仅保留请求传入的键(含值为None的情况)

Django Ninja中如何让Schema仅保留请求传入的键(含值为None的情况)

这个问题我之前也碰到过,确实挺闹心的——Pydantic默认会把Schema里所有可选字段都初始化为None,不管请求里有没有传,这就导致我们没法区分「用户没传这个字段」和「用户主动传了null」。不过有几个实用的办法可以解决这个问题:

方法一:用exclude_unset=True替代exclude_none=True

这是最简单的解决方案,直接修改你序列化Schema时的参数:

原来的代码:

for key, value in filters.dict(exclude_none=True).items():

改成:

for key, value in filters.dict(exclude_unset=True).items():

原理说明:

  • exclude_none=True会移除所有值为None的键,不管这个键是用户传的还是Schema默认的;
  • exclude_unset=True只会移除那些没有被请求显式设置过的键——也就是说,用户主动传了null的键会被保留,而Schema里默认存在但用户没传的键会被过滤掉。

比如你提到的请求:

{
  "major_version": {
    "exact": null
  },
  "app_name": {
    "icontains": "google"
  }
}

用exclude_unset=True序列化后得到的字典会是:

{
  "major_version": {"exact": None},
  "app_name": {"icontains": "google"}
}

这样你的循环就只会处理用户实际传入的键,包括那个值为None的exact,生成正确的Q(major_version__exact=None)查询条件。

方法二:用Undefined替代None作为字段默认值

如果需要更严格的控制(比如确保未传入的字段完全不出现Schema实例中),可以给Schema字段设置Undefined作为默认值:

首先导入Undefined:

from pydantic import Undefined

然后修改你的Schema:

class NumericalFilterSchema(Schema):
    gt: Optional[int] = Undefined
    lt: Optional[int] = Undefined
    gte: Optional[int] = Undefined
    lte: Optional[int] = Undefined
    exact: Optional[int] = Undefined

    class Config:
        extra = "forbid"

class StringFilterSchema(Schema):
    contains: Optional[str] = Undefined
    icontains: Optional[str] = Undefined
    exact: Optional[str] = Undefined

    class Config:
        extra = "forbid"

原理说明:

  • 当字段默认值是Undefined时,Pydantic不会自动初始化这个字段,只有当用户主动传入(包括传null)时,该字段才会出现在Schema实例中;
  • 此时你甚至不需要额外加exclude_unset=True,直接调用filters.dict()就能得到仅包含用户传入字段的字典。

这个方法更严谨,但需要修改所有Schema字段的默认值,适合对字段存在性要求严格的场景。

额外注意事项

如果你使用的是Pydantic v2(Django Ninja最新版本一般基于Pydantic v2),dict()方法已经被model_dump()替代,参数用法是一样的:

filters.model_dump(exclude_unset=True)

这样修改后,你就能准确区分用户没传的字段和主动传null的字段,生成符合预期的动态查询啦!

备注:内容来源于stack exchange,提问作者Leemosh

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.14 17:49:28