Использование методов класса документа 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