opened
BenCoDev
username_0
How could it be easier to integration custom field validation with current field validation ?

Implementing it with keyword validation on Field does not enable to customize ValidationError object.

Are there good practices about it with the current V of mongoengine ?

Cheers,
Custom validation of fields
issue
closed
BenCoDev
username_0
issue
created
wendy0402
username_1
hey @username_0 , can you share your strategy for this kind of case?
comment
created
neuronist
username_2
@JWDobken it's a bit dangerous to implement the validate method like that.

You're overriding the `StringField` validate method completely and `name_validation` is not calling the [`StringField.validate` method](https://github.com/MongoEngine/mongoengine/blob/master/mongoengine/fields.py#L91-L102) with super. This means that you can add a name bigger than 255 characters because you completely ignored that check. If you want to try it for yourself go ahead and do `mydoc = MyDoc(name="a"*300)` it runs and saves when it shouldn't. 

I found the [clean method approach](http://docs.mongoengine.org/guide/document-instances.html?highlight=clean%20document#pre-save-data-validation-and-cleaning) enough for my use case. Your example would look like this and now it also won't allow for names bigger than 255 characters and it should. I know this is not a specific field check but you can still encapsulate the checking of each field in a method and put them all on the clean method.

```python
from mongoengine import Document, StringField, ValidationError

class MyDoc(Document):
    name = StringField(min_length=3, max_length=255, required=True)
    
    @staticmethod
    def name_validation(name):
        if not name.startswith("a"):
            raise ValidationError("name does not start with 'a'")
        
    
    def clean(self):
        self.name_validation(self.name)

mydoc = MyDoc(name="aaa"*256)

# will throw ValidationError: ValidationError (MyDoc:None) 
# (String value is too long: ['name'])
mydoc.save()  

# ValidationError: ValidationError (MyDoc:None) 
# (name does not start with 'a': ['__all__'])
mydoc = MyDoc(name="aaa"*256).save()
```

I tried making it work with super but I wasn't sure how to access StringField validate, the closest I got was this but it isn't working, and I'm not willing to keep trying to make it work as the clean method works for me now.

I hope this helps as I was also a bit lost when trying to find a good way to do my custom checks before saving a document. If there's a better way or someone can explain how to properly override a Field validate method please do it.
comment
created
bagerard
username_3
The feature isn't well know and the online doc isn't up to date (due to a bug) but any fields can take a `validation` parameter which is a callable
E.g:
```
        def _not_empty(z):
            if not z:
                raise ValidationError('cantbeempty')

        class Person(Document):
            name = StringField(validation=_not_empty)
```

Note that:
- mongoengine>=0.18 expects the callable to raise a ValidationError
- mongoengine < 0.18 expects it to return a boolean (without possibility to customize the error message, its a generic one)
comment
created
neuronist
username_2
Thanks for that merge request, it will be very helpful. I didn't try the validation arg because I didn't get how it was supposed to use, also reading this "Generally this is deprecated in favor of the FIELD.validate method" confused me and led me to find another option like clean.
comment