我目前正在探索MongoEngine“对象文档映射器”的可能性。目前我不清楚的是,我可以在多大程度上将验证和对象创建逻辑移动到Document对象本身。
我的印象是它应该不是问题,但我找不到很多关于问题的例子/警告/最佳实践
我认为我需要覆盖save()方法,以便我可以调用我的自定义逻辑,但缺少示例会让我相信这可能是一种错误的方法......
欢迎使用mongoEngine的任何示例或对高质量代码库的引用。
答案 0 :(得分:22)
现在应该由implementing the clean()
method on a model完成自定义验证。
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()
定义
答案 1 :(得分:14)
你可以覆盖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
]
答案 2 :(得分:7)
您还可以覆盖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