user1724763
user1724763

Reputation:

Django ValidationError

According to https://docs.djangoproject.com/en/dev/ref/forms/validation/

   # Good
   ValidationError(
        _('Invalid value: %(value)s'),
        params={'value': '42'},
   )

   # Bad
   ValidationError(_('Invalid value: %s') % value)

The docs doesnt really explain why it is bad / good. Can someone give a concrete example?

Furthermore, when I inspect form.errors, I get something like 'Invalid: %(value)s'. How do I get the params from the Validation error and interpolate them into the error msg?

Edited

So is this considered good?

   ValidationError(
        _('Invalid value: %(value)s') % {'value': '42'},
   )

I think the real question is: why pass the variables separately via the params argument? Why not interpolate directly into the error msg (ignore named or positional interpolation for now)???

Edited

Ok, From the source @ https://github.com/django/django/blob/stable/1.5.x/django/forms/forms.py I don't think there is any way to retrieve ValidationError's params since the Form does not even save the ValidationError object itself. See code below.

class ValidationError(Exception):
    """An error while validating data."""
    def __init__(self, message, code=None, params=None):
        import operator
        from django.utils.encoding import force_text
        """
        ValidationError can be passed any object that can be printed (usually
        a string), a list of objects or a dictionary.
        """
        if isinstance(message, dict):
            self.message_dict = message
            # Reduce each list of messages into a single list.
            message = reduce(operator.add, message.values())

        if isinstance(message, list):
            self.messages = [force_text(msg) for msg in message]
        else:
            self.code = code
            self.params = params
            message = force_text(message)
            self.messages = [message]

class Form:
    ....
    def _clean_fields(...):
       ....
       except ValidationError as e:
            self._errors[name] = self.error_class(e.messages)  # Save messages ONLY
            if name in self.cleaned_data:
                del self.cleaned_data[name]

Upvotes: 8

Views: 6793

Answers (2)

twil
twil

Reputation: 6162

ValidationError is caught by the form validation routine and though it can just show a message, it's better to save the possibility of getting params of error; eg. field name, value that caused error and so on. It's stated just before the example you've provided.

In order to make error messages flexible and easy to override

Upvotes: 2

Alasdair
Alasdair

Reputation: 308779

If you have multiple parameters, they might appear in a different order when you translate the error message.

Named arguments allow you to change the order in which the arguments appear, without changing params. With a tuple of arguments, the order is fixed.

Note that you are linking to the development version of the Django docs. The validation error is not interpolating the parameters because you are using Django 1.5 or earlier. If you try your code in the 1.6 beta, then the parameters are interpolated into the error message.

Upvotes: 3

Related Questions