Enable Validators to defer string evaluation and handle new string format by xordoquy · Pull Request #3438 · encode/django-rest-framework (original) (raw)

This should fix #3354 and take over #3407.

There has been more difficulties than expected here due to several factors.

Due to a naive test during Validator instantiation any lazy translated message passed to the validator will be evaluated which will lead to the issue in #3354. This will only apply to Django 1.8+. For Django 1.7 DRF compact module was pulling the message without evaluation which is fine.
The faulty test is located here and the issue will be risen on Django bug tracker as discussed with a core dev.
This very reason lead to the removal of Django 1.8+ compatibility code which means the 4 Validators are now the same for every Django version.

Second issue was pretty painful and not that easy to solve.
Django uses the printf style formatting ("%()s") while DRF uses the new format one ("{}s").
Therefore it would lead to nowhere to let the Django's Validator evaluate the string on its own.
To work around the two formats, an additional argument is added to the DRF Validator.
Since the only case where the new format is used is through the default Field errors we now add the message to the Validator and specify it's using the "{" format - similar to what logging's formatter do, thanks @nedbat for pointing it to me.
If a user changes the default_error_messages it'll still be interpreted with the new format so it's invisible.
If a user chooses to provide its own Validator, he would be able to use the old format as before this change.