Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Django: How to override unique_together error message?

In a model's Meta class, I define a unique_together. I have a ModelForm based on this model. When I call is_valid on this ModelForm, an error will automatically raised if unique_together validation fails. That's all good.

Now my problem is that I'm not satisfied with the default unique_together error message. I want to override it. How can I do that? For a field related error, I can easily do that by setting error_messages on the field parameters. But unique_together is a non field error. How can I override a non field error message?

like image 395
Georgie Porgie Avatar asked Oct 22 '10 02:10

Georgie Porgie


4 Answers

You can do this since Django 1.7

from django.forms import ModelForm
from django.core.exceptions import NON_FIELD_ERRORS

class ArticleForm(ModelForm):
    class Meta:
        error_messages = {
            NON_FIELD_ERRORS: {
                'unique_together': "%(model_name)s's %(field_labels)s are not unique.",
            }
        }
like image 100
jifeng.yin Avatar answered Dec 22 '22 00:12

jifeng.yin


Update 2016/10/20: See jifeng-yin's even nicer answer below for Django >= 1.7

The nicest way to override these error messages might be to override the unique_error_message method on your model. Django calls this method to get the error message whenever it encounters a uniqueness issue during validation.

You can just handle the specific case you want and let all other cases be handled by Django as usual:

def unique_error_message(self, model_class, unique_check):
    if model_class == type(self) and unique_check == ('field1', 'field2'):
        return 'My custom error message'
    else:
        return super(Project, self).unique_error_message(model_class, unique_check)
like image 27
Sam Bull Avatar answered Dec 21 '22 23:12

Sam Bull


For DRF serializers you can use this

from rest_framework import serializers


class SomeSerializer(serializers.ModelSerializer):


    class Meta:
        model = Some
        validators = [
            serializers.UniqueTogetherValidator(
                queryset=model.objects.all(),
                fields=('field1', 'field2'),
                message="Some custom message."
            )
        ]

Here is the original source.

like image 39
Vaghinak Avatar answered Dec 21 '22 23:12

Vaghinak


After a quick check, it seems that unique_together validation errors are hard-coded deep in django.db.models.Model.unique_error_message :

def unique_error_message(self, model_class, unique_check):
    opts = model_class._meta
    model_name = capfirst(opts.verbose_name)

    # A unique field
    if len(unique_check) == 1:
        field_name = unique_check[0]
        field_label = capfirst(opts.get_field(field_name).verbose_name)
        # Insert the error into the error dict, very sneaky
        return _(u"%(model_name)s with this %(field_label)s already exists.") %  {
            'model_name': unicode(model_name),
            'field_label': unicode(field_label)
        }
    # unique_together
    else:
        field_labels = map(lambda f: capfirst(opts.get_field(f).verbose_name), unique_check)
        field_labels = get_text_list(field_labels, _('and'))
        return _(u"%(model_name)s with this %(field_label)s already exists.") %  {
            'model_name': unicode(model_name),
            'field_label': unicode(field_labels)
        }

So maybe you should try to override this method from your model, to insert your own message !?

However, I haven't tried, and it seems a rather brutal solution ! But if you don't have something better, you might try...

like image 31
sebpiq Avatar answered Dec 21 '22 23:12

sebpiq