2010-10-22 106 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