Использование методов класса MongoEngine Document для пользовательской проверки и предварительных сбережений
В настоящее время я изучаю возможности "компоновщика документов объекта MongoEngine". В настоящее время мне не ясно, насколько я могу перенести мою логику проверки и создания объекта в объекты Document.
У меня сложилось впечатление, что это не должно быть проблемой, но я не нахожу много примеров/предостережений/лучших практик в отношении проблем, таких как
- Пользовательские функции проверки, которые автоматически вызывают функцию save() для оценки допустимости содержимого поля;
- Автоматическая генерация идентификатора в файле save() на основе хэша содержимого поля;
Я думаю, мне нужно переопределить метод save(), чтобы я мог вызвать свою собственную логику, но отсутствие примеров заставляет меня поверить, что это может быть неправильный подход...
Любые примеры или ссылки на высококачественные кодовые базы с использованием mongoEngine приветствуются.
Ответы
Ответ 1
Вы можете переопределить 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
Пользовательская проверка теперь должна выполняться реализующей метод 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()
до проверки модели на основе правил, установленных в определении модели.
Ответ 3
Вы также можете переопределить метод проверки в документе, но вам нужно будет усвоить ошибки документа Суперкласса, чтобы вы могли добавить к ним свои ошибки.
Это, к сожалению, зависит от внутренних деталей реализации в 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