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

MongoEngine中为Document与EmbeddedDocument添加通用字段及方法报错求助

解决MongoEngine中Document和EmbeddedDocument复用时间戳字段的问题

你的问题根源在于Python2中旧式类的限制:SikkaBase没有继承object,属于旧式类,而MongoEngine的元类在处理多重继承时需要访问类的__class__属性,旧式类没有这个属性,所以抛出了AttributeError。另外,你写的save和update方法里的super调用逻辑也需要调整。

下面提供两种可行的解决方案:

方案一:修正Mixin类为新式类

把SikkaBase改成新式类(继承object),并修正方法中的super调用逻辑,确保正确触发MongoEngine基类的方法:

import datetime
from mongoengine import Document, EmbeddedDocument, DateTimeField, BooleanField

class SikkaBase(object):  # 继承object成为新式类
    created_on = DateTimeField(default=datetime.datetime.now)
    updated_on = DateTimeField(default=datetime.datetime.now)
    is_deleted = BooleanField(default=False)

    def save(self, *args, **kwargs):
        self.updated_on = datetime.datetime.now()
        # 根据继承链自动调用对应基类的save方法
        return super(SikkaBase, self).save(*args, **kwargs)

    def update(self, *args, **kwargs):
        self.updated_on = datetime.datetime.now()
        # 注意:EmbeddedDocument本身没有update方法,该方法仅对Document子类生效
        return super(SikkaBase, self).update(*args, **kwargs)

class SikkaBaseDocument(Document, SikkaBase):
    meta = {
        'abstract': True
    }

class SikkaEmbeddedBaseDocument(EmbeddedDocument, SikkaBase):
    meta = {
        'abstract': True
    }

方案二:使用MongoEngine信号(更优雅解耦)

MongoEngine提供了pre_save信号机制,可以在保存任何文档(包括嵌入式文档)之前自动更新时间戳,这种方式不需要依赖多重继承,代码更解耦:

import datetime
from mongoengine import Document, EmbeddedDocument, DateTimeField, BooleanField
from mongoengine.signals import pre_save

def update_timestamp(sender, document, **kwargs):
    document.updated_on = datetime.datetime.now()
    # 仅对新创建的文档设置created_on(覆盖默认值逻辑)
    if not document.created_on:
        document.created_on = datetime.datetime.now()

# 定义带通用字段的抽象基类
class TimestampedDocument(Document):
    created_on = DateTimeField()
    updated_on = DateTimeField()
    is_deleted = BooleanField(default=False)
    meta = {
        'abstract': True
    }

class TimestampedEmbeddedDocument(EmbeddedDocument):
    created_on = DateTimeField()
    updated_on = DateTimeField()
    is_deleted = BooleanField(default=False)
    meta = {
        'abstract': True
    }

# 给两个抽象基类注册信号,所有子类都会自动触发时间戳更新
pre_save.connect(update_timestamp, sender=TimestampedDocument)
pre_save.connect(update_timestamp, sender=TimestampedEmbeddedDocument)

两种方案都能解决你的代码复用问题,方案二更符合MongoEngine的设计思路,也更灵活,推荐优先使用。

内容的提问来源于stack exchange,提问作者Varun Jain

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.28 06:59:36