2010-10-22 19 views
14

Nella classe Meta di un modello, definisco un unique_together. Ho un ModelForm basato su questo modello. Quando chiamo is_valid su questo ModelForm, verrà generato automaticamente un errore se la convalida unique_together fallisce. Va tutto bene.Django: Come sovrascrivere un messaggio di errore unique_together?

Ora il mio problema è che non sono soddisfatto del messaggio di errore unique_together predefinito. Voglio scavalcarlo. Come lo posso fare? Per un errore relativo al campo, posso farlo facilmente impostando error_messages sui parametri del campo. Ma unique_together è un errore non sul campo. Come posso ignorare un messaggio di errore non sul campo?

+0

io ti immagino meglio mark un'altra risposta come accettata invece della mia poiché Django 1.7 ha apportato importanti cambiamenti che hanno anche effetto sulla mia risposta. – FallenAngel

risposta

27

Si può fare this in 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.", 
      } 
     } 
+1

sembra molto sexy;) – andi

+0

Questo è ancora meglio! –

+1

Una nota importante: devi importare 'NON_FIELD_ERRORS' da' django.core.exceptions'. –

1

Dopo un rapido controllo, sembra che unique_together errori di validazione sono hard-coded nel profondo 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) 
     } 

Così forse si dovrebbe cercare di ignorare questo metodo dal modello, per inserire il tuo messaggio!?

Tuttavia, non ho provato, e sembra una soluzione piuttosto brutale! Ma se non hai qualcosa di meglio, potresti provare ...

+1

Sì, è hardcoded. Odio. Il team di Django avrebbe dovuto prendere in considerazione lo scenario dello sviluppatore che sovrascriveva il messaggio di errore non sul campo. –

0

Avviso: Molto è cambiato in Django da questa risposta. Quindi meglio controllare altre risposte ...

Se sebpiq è vero (visto che non verificare il codice sorgente), poi c'è una soluzione possibile che si può fare, ma è il modo più duro ...

È possibile definire una regola di convalida nel modulo, as it described here

potete vedere examples di convalida con più di un campo, in modo da utilizzare questo metodo, è possibile definire un unico insieme controllare prima di Django standard di controllo unico eseguito ...

Oppure il peggiore, puoi fare una convalida nella tua v prima di provare a salvare gli oggetti ...

+0

questo non è più vero per Django> = 1.7 – nuts

-1

Si potrebbe dare un'occhiata a sostituire django/db/models/base.py:Model._perform_unique_checks() nel modello.

In questo metodo è possibile ottenere gli errori "originali":

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

- quindi modificare e restituirli verso l'alto.

+0

È molto rischioso sovrascrivere metodi "privati" come questo. Non si sa mai quando potrebbero cambiare o addirittura scomparire – richard

24

Aggiornamento 2016/10/20: Vedere jifeng-yin 's anche la risposta più bello sotto per Django> = 1.7

il modo più bello per ignorare questi messaggi di errore potrebbe essere l'override del metodo unique_error_message del modello. Django chiama questo metodo per ottenere il messaggio di errore ogni volta che incontra un problema di univocità durante la convalida.

Si può solo gestire il caso specifico che si desidera e lasciare tutti gli altri casi trattati da Django come al solito:

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

Questo corrisponde a una soluzione che ho visto pubblicata su un [blog] (http://chriskief.com/2013/11/20/customize-djangos-unique_together-error-message/). Ma ho una domanda ... perché dobbiamo controllare se 'model_class' è di tipo' self'? – HorseloverFat

+0

questo non è più il modo più "carino". almeno per Django> = 1.7. Vedi la risposta di @jifeng.yin – nuts

Problemi correlati