Использование методов класса документа MongoEngine для пользовательской проверки и предварительного сохранения крючков
в настоящее время я изучаю возможности MongoEngine "object document mapper". В настоящее время мне неясно, в какой степени я могу переместить логику проверки и создания объектов в сами объекты документа.
У меня сложилось впечатление, что это не должно быть проблемой, но я не нахожу много примеров/предостережений/лучших практик в отношении вопросов, как
- пользовательские функции проверки, которые автоматически вызываются save () для оценки если содержимое поля допустимо;
- автоматическая генерация идентификатора на save (), на основе хэша содержимого поля;
Я думаю, что мне нужно переопределить метод save (), чтобы я мог вызвать свою пользовательскую логику, но отсутствие примеров заставляет меня полагать, что это может быть неправильный подход...
любые примеры или ссылки на высококачественные кодовые базы с использованием mongoEngine приветствуются.
3 ответов
можно переопределить 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()
Edit: тем не менее, вы должны быть осторожны, используя clean()
как это называется с validate()
до проверки модели на основе правил, установленных в определении модели.
вы также можете переопределить метод validate в документе, но вам нужно будет проглотить ошибки документа суперкласса, чтобы вы могли добавить к ним свои ошибки
это, к сожалению, зависит от внутренних деталей реализации в 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