views:

45

answers:

3

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?

A: 

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...

sebpiq
Yes, it IS hardcoded. Hate it. The django team should have taken into consideration of the scenario of developer overriding non field error message.
Georgie Porgie
A: 

If what sebpiq is true( since i do not check source code), then there is one possible solution you can do, but it is the hard way...

You can define a validation rule in your form, as it described here

You can see examples of validation with more than one field, so by using this method, you can define a unique together check before standard django unique check executed...

Or the worst one, you can do a validation in your view before you try to save the objects...

FallenAngel
A: 

You might take a look at overriding django/db/models/base.py:Model._perform_unique_checks() in your model.

In that method you can get the "original" errors:

    errors = super(MyModel, self)._perform_unique_checks(unique_checks)

-- then modify and return them upwards.

Tomasz Zielinski