2011-05-23 14 views
13

Actualmente estoy explorando las posibilidades del "mapeador de documentos de objetos" de MongoEngine. Lo que actualmente no tengo claro es hasta qué punto puedo mover mi validación y la lógica de creación de objetos a los objetos del documento en sí.Uso de MongoEngine Métodos de clase de documento para validación personalizada y ganchos de guardado previo

Tengo la impresión de que no debería ser un problema, pero no estoy encontrando una gran cantidad de ejemplos/advertencias/mejores prácticas con respecto a cuestiones como

  • funciones de validación personalizada que se llaman automáticamente en Guardar () para evaluar si los contenidos del campo son válidos;
  • Generación automática del identificador en save(), basado en el hash del contenido de un campo;

creo que es necesario reemplazar el método save(), por lo que puedo llamar a mi lógica personalizada, pero la falta de ejemplos me lleva a creer que eso puede ser un enfoque equivocado ...

Se aceptan ejemplos o referencias a bases de código de alta calidad con mongoEngine.

Respuesta

14

Puede anular save(), con la advertencia habitual de que debe llamar al método de la clase principal.

Si encuentra que desea agregar ganchos de validación para todos sus modelos, es posible considerar la creación de una clase personalizada niño de Document algo como:

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) 

continuación, se pueden definir ganchos para una clase de modelo que figura en una forma bastante natural:

class SomeModel(MyDocument): 
    # fields... 

    _pre_save_hooks = [ 
     some_callable, 
     another_callable 
    ] 
7

también podría anular el método de validación de documentos, pero que había necesidad de tragar los errores del documento de la superclase para que pueda añadir sus errores les

Desafortunadamente, esto depende de los detalles internos de implementación en MongoEngine, así que quién sabe si se romperá en el futuro.

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) 

Además, hay un apoyo adecuado de la señal ahora en MongoEngine para el manejo de otros tipos de ganchos (como la generación de identificador que usted ha mencionado en la pregunta).

http://mongoengine.readthedocs.io/en/latest/guide/signals.html

+0

El enlace está roto, el correcto es http://mongoengine.readthedocs.org/en/latest/guide/signals.html al lado de eso, sugeriría no seguir este enfoque si hay otras formas de resolver el problema (como se sugiere en las otras respuestas). En mi opinión, el mantenimiento de su código disminuirá al interceptar el flujo de excepción de una biblioteca. – karfau

20

validación personalizada ahora debe ser realizado por 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() 

Editar: Dicho esto, usted tiene que tener cuidado usando clean() como se le llama desde validate() antes de validar el modelo basado en las las normas establecidas en la definición del modelo.

+2

La mejor manera en mi opinión. También vea el comentario en la función 'clean()' en el código fuente de MongoEngine: https://github.com/MongoEngine/mongoengine/blob/master/mongoengine/base/document.py # L230 - 'Gancho para realizar limpieza de datos a nivel de documento antes de ejecutar la validación. Cualquier ValidationError generado por este método no se asociará con un campo particular; tendrá una asociación de casos especiales con el campo definido por NON_FIELD_ERRORS. Por lo tanto, si desea la validación de campo, creo que debe escribir un campo personalizado. – rednaw

Cuestiones relacionadas