2010-10-22 127 views
14

在模型的Meta类中,我定义了一个unique_together。我有一个基于这个模型的ModelForm。当我在此ModelForm上调用is_valid时,如果unique_together验证失败,则会自动产生错误。这很好。Django:如何覆盖unique_together错误消息?

现在我的问题是,我不满意默认的unique_together错误消息。我想重写它。我怎样才能做到这一点?对于与字段相关的错误,我可以通过在字段参数上设置error_messages来轻松完成此操作。但unique_together是非现场错误。我如何覆盖非字段错误消息?

+0

我想你最好标记另一个答案接受而不是我的,因为Django 1.7做出了重要的改变,这也影响了我的答案。 – FallenAngel 2017-07-21 08:10:34

回答

27

你可以在Django做this 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.", 
      } 
     } 
+1

看起来很性感;) – andi 2014-08-27 07:16:45

+0

这样更好! – 2015-06-30 15:36:14

+1

重要说明:您必须从'django.core.exceptions'中导入'NON_FIELD_ERRORS'。 – 2017-03-13 19:54:58

1

快速检查后,似乎unique_together验证错误是硬编码在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) 
     } 

因此,也许你应该尝试从模型覆盖此方法,插入自己的消息!?

但是,我没有尝试过,它似乎是一个相当残酷的解决方案!但如果你没有更好的东西,你可以尝试...

+1

是的,它是硬编码的。讨厌它。 django团队应该考虑开发人员覆盖非现场错误消息的场景。 – 2010-10-22 16:28:03

0

注意:自从这个答案以来,Django发生了很大的变化。所以,最好先检查一下其他的答案...

如果什么sebpiq是真的(因为我不检查源代码),然后有一个 可能的解决方案,你可以做,但它是艰辛的道路......

您可以在表单定义的验证规则,as it described here

你可以看到验证examples与多个字段,所以使用这种方法,你可以定义一个独特的一起检查标准的Django独特的检查执行之前...

或者最糟糕的一个,你可以在你的v中进行验证在尝试保存对象之前...

+0

Django> = 1.7 – nuts 2016-10-18 12:16:25

-1

您可以在模型中查看重写django/db/models/base.py:Model._perform_unique_checks()

在该方法中,你可以得到的“原始”的错误:

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

- 然后修改和向上返回它们。

+0

这不是真的,重写这样的“私有”方法是非常危险的。你永远不知道他们什么时候可能改变甚至消失 – richard 2017-03-03 01:35:40

24

更新2016年10月20日:见jifeng-yin的下面Django的甚至更好的答案> = 1.7

来覆盖这些错误消息可能是覆盖在你的模型unique_error_message方法的最好方式。 Django在验证期间遇到唯一性问题时会调用此方法来获取错误消息。

你可以只处理所需的特定情况下,让所有其他情况下被Django像往常一样处理:

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) 
+0

这与我在[博客]上发布的解决方案相匹配(http://chriskief.com/2013/11/20/customize-djangos-unique_together-error-message/)。但是我有一个问题......为什么我们需要检查'model_class'是'self'类型的? – HorseloverFat 2014-05-23 10:18:43

+0

这不是真正的“最好”的方式了。至少对于Django> = 1.7来说。看@ jifeng.yin的回答 – nuts 2016-10-18 12:15:41