使用MongoEngine Document类方法进行自定义验证和预保存挂钩

|| 我目前正在探索MongoEngine“对象文档映射器”的可能性。目前尚不清楚的是,我可以在多大程度上将验证和对象创建逻辑移到Document对象本身。 我的印象是这应该不是问题,但是我没有找到很多有关问题的例子/建议/最佳实践。 自定义验证函数,将自动在save()上调用以评估字段内容是否有效; 根据字段内容的哈希值,自动在save()上生成标识符; 我认为我需要重写save()方法,以便可以调用自定义逻辑,但是缺少示例使我相信这可能是错误的方法... 欢迎使用mongoEngine提供任何示例或对高质量代码库的引用。     
已邀请:
您可以用必须声明父类的方法的通常警告来覆盖
save()
。 如果发现要向所有模型添加验证钩子,则可以考虑创建自定义子类
Document
,例如:
class MyDocument(mongoengine.Document):

    def save(self, *args, **kwargs):
        for hook in self._pre_save_hooks:
            # the callable can raise an exception if
            # it determines that it is inappropriate
            # to save this instance; or it can modify
            # the instance before it is saved
            hook(self):

        super(MyDocument, self).save(*args, **kwargs)
然后,您可以以相当自然的方式为给定的模型类定义钩子:
class SomeModel(MyDocument):
    # fields...

    _pre_save_hooks = [
        some_callable,
        another_callable
    ]
    
现在应该通过在模型上实现
clean()
方法来完成自定义验证。
class Essay(Document):
    status = StringField(choices=(\'Published\', \'Draft\'), required=True)
    pub_date = DateTimeField()

    def clean(self):
        \"\"\"
        Ensures that only published essays have a `pub_date` and
        automatically sets the pub_date if published and not set.
        \"\"\"
        if self.status == \'Draft\' and self.pub_date is not None:
            msg = \'Draft entries should not have a publication date.\'
            raise ValidationError(msg)

        # Set the pub_date for published items if not set.
        if self.status == \'Published\' and self.pub_date is None:
            self.pub_date = datetime.now()
编辑:也就是说,在根据模型定义中设置的规则验证模型之前,必须小心使用
clean()
,因为它是从
validate()
调用的。     
您也可以覆盖Document上的validate方法,但是您需要吞下超类Document错误,以便可以将错误添加到其中 不幸的是,这依赖于MongoEngine中的内部实现细节,因此谁知道它将来是否会失效。
class MyDoc(Document):
    def validate(self):
        errors = {}
        try:
            super(MyDoc, self).validate()
        except ValidationError as e:
            errors = e.errors

        # Your custom validation here...
        # Unfortunately this might swallow any other errors on \'myfield\'
        if self.something_is_wrong():
            errors[\'myfield\'] = ValidationError(\"this field is wrong!\", field_name=\'myfield\')

        if errors:
            raise ValidationError(\'ValidationError\', errors=errors)
另外,MongoEngine中现在有适当的信号支持,可以处理其他种类的钩子(例如您在问题中提到的标识符生成)。 http://mongoengine.readthedocs.io/en/latest/guide/signals.html     

要回复问题请先登录注册