2011-05-23 1 views
13

В настоящее время я изучаю возможности MongoEngine «Document document mapper». В настоящее время мне не ясно, насколько я могу перенести мою логику проверки и создания объектов на объекты документа самостоятельно.Использование MongoEngine Методы класса документа для пользовательских проверок и предварительных сбережений.

У меня создалось впечатление, что это не должно быть проблемой, но я не нахожу много примеров/предостережений/наилучшей практики в отношении вопросов,

  • Пользовательские функции проверки, которые автоматически вызывается сохранить (), чтобы оценить, действительно ли полевое содержимое;
  • Автоматическая генерация идентификатора на save(), основанная на хеше содержимого поля;

Я думаю, что нужно переопределить метод сохранения(), так что я могу назвать свою собственную логику, но отсутствие примеров приводит меня к мысли, что это может быть неправильный подход ...

Любые примеры или ссылки на высококачественные кодовые базы с использованием mongoEngine приветствуются.

ответ

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 
    ] 
7

вы можете также переопределить метод проверки на документе, но вы должны проглотить суперкласс ошибки документа, так что вы можете добавить свои ошибки в них

Это, к сожалению, зависит от внутренних деталей реализации в 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

+0

Ссылка не работает, правильный вариант - http://mongoengine.readthedocs.org/en/latest/guide/signals.html, помимо этого я бы предложил не идти этим путем, если есть другие способы решения проблемы (как предложено в других ответах). По моему мнению, ремонтопригодность вашего кода будет уменьшаться при перехвате потока исключений библиотеки. – karfau

20

Пользовательские проверки должны теперь быть сделано 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() 

Edit: Тем не менее, вы должны быть осторожны при использовании clean() как он вызывается из validate() до проверки модели на основе правил, установленных в вашем определении модели.

+2

Лучший способ, на мой взгляд. Также см. Комментарий в функции 'clean()' в исходном коде MongoEngine: https://github.com/MongoEngine/mongoengine/blob/master/mongoengine/base/document.py # L230 - «Захват для очистки данных уровня документа перед выполнением проверки. Любое действие ValidationError, поднятое этим методом, не будет связано с конкретным полем; он будет иметь специальную ассоциацию с полем , определяемым NON_FIELD_ERRORS.' Итак, если вы хотите проверить на уровне поля, я думаю, вы должны написать настраиваемое поле. – rednaw

Смежные вопросы