2

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?

1 Answer 1

3

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.

Sign up to request clarification or add additional context in comments.

3 Comments

Thanks, that's a working solution. However doesn't it mix the model layer (limit definition) with the representation layer (error message text)? I would prefer to define the error text separately, where I am defining how my site interacts with the user (i.e. in the views and templates). Is it possible to access the limit_value outside the validation definition? Anything like w.validators[0].limit_value?
That's a great point. I'll update my answer with my recent findings.
Awesome. Exactly what I've been looking for. Thanks a lot.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.