Change error_messages for a specific error in specific a field and for another error for all fields

Say I have 30 fields in my model where one of them is link.

I want to throw a specific error when link is invalid, and I want to change the required error for all the fields (including link).

If I write the following form:

class product_prices_form(forms.ModelForm):

    class Meta:
        error_messages = {"link":{"invalid": "Not really valid"}, #Only change invalid for link-field
"required":"You forgot something here!"} #Change the "required" error for all fields
        model = my_model

the required error is not overwritten. If I move it into the “link” dict, it works fine, but creating that for all the remaining 29 fields i doubt is the right way to do.

I believe (am not 100% certain) that error_messages is an attribute of the fields, not of the form. (That is consistent with the behavior you’re seeing and what I’m seeing in the source.)

I’m guessing the easiest way to do this would be to write a custom clean method that, after calling super().clean(), iterates through the errors list and change the text of any instance of a required error.

I don’t think I understand that? If I dont have the link: first e.g just error_messages = {"invalid": _("not really valid")} that overwrites all invalid messages, correct? What I don’t understand if why it cannot be chained

I don’t know, does it? I’m not seeing that from the docs I’m reading - particularly in the modelform_factory method:

error_messages is a dictionary of model field names mapped to a dictionary of error messages.

and in the Overriding the default fields paragraph:

Similarly, you can specify the labels , help_texts and error_messages attributes of the inner Meta class if you want to further customize a field.

And if you follow the logic in the source code, you’ll see that error_messages are applied on a per-field basis, not a global form basis. So I would be a bit surprised if it worked the way you’re describing for field-level errors.
(Note: All my comments above are referring to field-level errors. non_field_errors are handled differently.)

You can define the error_messages per field via the ModelForm.Meta as per this part of the docs. However as Ken said and you’ve discovered, it’s not possible to change this globally, or declare a value to use across all the fields of a form.

That doesn’t mean your stuck redefining this multiple times either. You could do any of the following:

  • Subclass ModelForm and change the error messages in the __init__ method for all fields.
  • Subclass the built-in fields and use those rather than forms.CharField, etc.
  • Create a function that that returns the dict of error messages, and call that when setting the error_messages= parameter of the form fields. forms.CharField(error_messages=custom_messages())

There are probably other options available too, such as customizing the Meta class to allow you to specify a form wide value, but I’m less sure of the work involved.