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

如何为Pydantic V2 BaseModel添加类级__getattr__行为?

解决方案:安全实现Pydantic V2类属性访问生成过滤对象

核心思路

避免直接覆盖元类的__getattr__与Pydantic内部逻辑冲突,而是在自定义元类中先委托Pydantic处理属性访问,仅当Pydantic无法找到属性时,再检查是否为模型字段并返回过滤对象,同时保证多级子类继承时逻辑正常生效。

具体实现步骤

1. 自定义元类继承ModelMetaclass

from pydantic._internal._model_construction import ModelMetaclass
from pydantic import BaseModel

class MetaGetFilterPydantic(ModelMetaclass):
    def __getattr__(cls, name):
        try:
            # 优先让Pydantic元类处理属性访问,保障内部逻辑正常
            return super().__getattr__(name)
        except AttributeError:
            # 检查属性是否为当前模型的有效字段
            if name in cls.model_fields:
                # 返回自定义过滤对象
                return MyFilterObject(cls, name)
            # 非字段属性则抛出原错误
            raise

2. 定义基础模型类

让你的ORM基础模型使用上述自定义元类:

class Model(BaseModel, metaclass=MetaGetFilterPydantic):
    class Config:
        # 根据业务需求配置Pydantic选项,比如冻结模型等
        pass

3. 处理多级子类继承问题

若多级子类仍出现失效情况,可在元类的__new__方法中确保模型构建完成后字段信息同步:

class MetaGetFilterPydantic(ModelMetaclass):
    def __new__(mcs, name, bases, namespace, **kwargs):
        # 先让Pydantic完成模型类的初始化
        cls = super().__new__(mcs, name, bases, namespace, **kwargs)
        # 可选:提前同步继承的字段信息,确保多级子类字段可被识别
        return cls

    def __getattr__(cls, name):
        try:
            return super().__getattr__(name)
        except AttributeError:
            if name in cls.model_fields:
                return MyFilterObject(cls, name)
            raise

4. 实现过滤对象逻辑

MyFilterObject需接收模型类和字段名,用于后续生成查询条件:

class MyFilterObject:
    def __init__(self, model_cls, field_name):
        self.model_cls = model_cls
        self.field_name = field_name

    def __gt__(self, value):
        return {"$gt": {self.field_name: value}}
    
    def __eq__(self, value):
        return {"$eq": {self.field_name: value}}
    
    def __and__(self, other):
        return {"$and": [self, other]}
    
    # 根据业务需求重载其他操作符(如__lt__、__or__等)

关键注意事项

  • 不可跳过Pydantic属性处理:必须优先调用super().__getattr__,否则会破坏Pydantic内部的字段访问、模型配置等核心逻辑。
  • 依赖model_fields而非__annotations__:Pydantic V2中model_fields是处理后的完整字段集合,包含继承字段、默认值等信息,比直接使用__annotations__更可靠。
  • 多级子类自动继承元类:由于基础Model已指定自定义元类,所有继承自Model的子类都会自动使用该元类,无需额外配置。

内容的提问来源于stack exchange,提问作者Fredrik Nilsson

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.09 09:55:33