texnic
texnic

Reputation: 4098

Model validation values in custom Django form error messages

I have created a Django form:

class AddFaceForm(forms.ModelForm):

    class Meta:
        model = Face
        fields = ('person', 'x', 'y', 'w', 'h')

In the Face model, w is defined as

w = models.DecimalField(
    'Relative width',
    validators=[MinValueValidator(0.05), MaxValueValidator(1)]
)

If a user enters 0 for the width, the error message Django returns upon form validation is

Ensure this value is greater than or equal to 0.05.

So it nicely contains the value from the MinValueValidator. I would like to change it to "Relative width must be >= 0.05".

To achieve it, I tried customising errors in AddFaceForm Meta

class AddFaceForm(forms.ModelForm):

    class Meta:
        model = Face
        fields = ('person', 'x', 'y', 'w', 'h')
        error_messages = {
            'w': {
                'min_value': 'Relative width must be >= 0.05'
            }
        }

But this means hard-coding the 0.05 value. I would like to read it from the model definition. How can this be done?

Upvotes: 2

Views: 1689

Answers (1)

Dwayne Crooks
Dwayne Crooks

Reputation: 2857

Great question.

MinValueValidator is a subclass of BaseValidator. And, BaseValidator takes an optional message in its constructor. From the code you can see that the message can use the following three parameters: limit_value, show_value and value. limit_value is the minimum value for the validator which is 0.05 in this case. show_value is the cleaned value the user enters and value is the raw value they enter. Hence, you can do the following to achieve your goal:

from django.core.validators import MinValueValidator
from django.db import models
from django.utils.translation import ugettext_lazy as _


class Face(models.Model):
    w = models.DecimalField(
        'Relative width',
        max_digits=5,
        decimal_places=2,
        validators=[MinValueValidator(0.05, _('Relative width must be >= %(limit_value)s'))],
    )

Alternatively, if you'd rather specify the error message in a form then you can do the following:

from django import forms
from django.utils.translation import ugettext_lazy as _

from .models import Face


class FaceForm(forms.ModelForm):
    class Meta:
        model = Face
        fields = ['w']
        error_messages = {
            'w': {
                'min_value': _('Relative width must be >= %(limit_value)s')
            }
        }

The DecimalField docs tell you that you can interpolate limit_value.

Upvotes: 3

Related Questions