2009-05-15 12 views
8

Ho un campo di stato che ha 3 valori: in sospeso, attivato e rifiutato. Se sto cambiando il valore dello stato che voglio ho un controllo che non può essere attivato in sospeso. I non voglio scrivere stored-procs per questo. Posso avere il valore precedente in Django prima di salvare?Come verificare la transizione del valore in Django (django-admin)?

Significa nuovo e vecchio valore.

+0

+1 - Mi stavo chiedendo la stessa cosa.Nel mio caso c'è un lavoro pesante che viene svolto con un metodo di salvataggio che è necessario solo se un campo in un particolare sottoinsieme di campi del modello è cambiato, e ho cercato un modo per verificare se questo è il caso . Grazie! –

risposta

10
def clean_status(self): 
    status = self.cleaned_data.get('status') 
    if status == 'pending': 
     if self.instance and self.instance.status == 'activated': 
      raise forms.ValidationError('You cannot change activated to pending') 

    return status 

Questo metodo è da aggiungere in un Form sottoclasse. Il suo nome è clean_FIELD_NAME.

cleaned_data contiene valori precedenti. Il nuovo valore è memorizzato in self.instance.

In alternativa, il metodo validate() può essere aggiunto a una sottoclasse forms.Field. See Django documentation.

+0

hey Dominic Rodger puoi aiutarti in 'inline-django'. La mia domanda in django – ha22109

8

È possibile eseguire questa operazione in un metodo save sostituito. La cosa da ricordare è che le istanze del modello Django non sono gli oggetti del database vero e proprio, ma solo i loro valori vengono caricati da lì. Quindi puoi tornare facilmente al database prima di salvare il tuo oggetto corrente per ottenere i valori esistenti.

def save(self, *args, **kwargs): 
    if self.status == 'pending': 
     old_instance = MyClass.objects.get(pk=self.pk) 
     if old_instance.status == 'activated': 
       raise SomeError 
    super(MyModel, self).save(*args, **kwargs) 

Attualmente non esiste un modo valido per restituire un messaggio di errore all'utente diverso dall'aumentare un'eccezione. È in corso un progetto Google Summer of Code per abilitare la "validazione del modello", ma non sarà pronto per alcuni mesi.

Se si desidera eseguire un'operazione simile nell'amministratore, il modo migliore è definire un ModelForm personalizzato con un metodo sostituito clean(). Tuttavia, questa volta poiché questo è un modulo, hai già accesso ai vecchi valori senza colpire nuovamente il db. Un altro vantaggio è che è possibile restituire un errore di convalida del modulo all'utente.

+0

perché probabilmente dovresti sovrascrivere il metodo ModelAdmin.save_model: http://docs.djangoproject.com/en/dev/ref/contrib/admin/#modeladmin-methods – ohnoes

+0

Ho aggiunto un'alternativa usando l'admin sopra. –

+0

la condizione if deve essere se self.instance e self.instance.status == 'attivato': raise forms.ValidiationError – ha22109

0

Invece di ignorare il metodo di salvataggio, non sarebbe un buon posto per utilizzare i segnali? Intercettare il salvataggio prima del commit, controllare il valore corrente nel database e inoltrare il salvataggio o rifiutarlo?

Ora non sono sicuro se il segnale blocca la richiesta di salvataggio o se accade asynch, quindi sentitevi liberi di ridimensionare questa risposta se non è possibile utilizzare un segnale per impedire che il salvataggio si verifichi alla convalida.

Sono contrario ai metodi incorporati di sovrascrittura se esiste un altro strumento integrato che funziona altrettanto bene.

+1

Penso che sovrascrivere save() e delete() possa essere una buona pratica. Ho una classe Foto e miniatura. Il pollice ha un oggetto = models.ForeignKey (Foto). photo.delete() viene sovrascritto e cancellerà tutti i pollici (per t in self.thumbnail_set.all(): t.delete()) prima di eseguire super (Photo, self) .delete(). Se la rimozione del pollice sarebbe effettuata in un segnale, il mantenimento del codice sarebbe più difficile. – vikingosegundo

+0

ma __init__ I wolud non sovraccaricheranno mai. Vorrei usare il segnale invece. – vikingosegundo

1

Questa è stata la risposta altrove su Stack Overflow, ma il modo corretto è quello di utilizzare qualcosa come this per tracciare se i campi sono sporchi. Quindi potresti usare un segnale per indicare che qualcosa è cambiato e che è importante. (ad esempio il tuo campo)

0

Trovato questo thread durante la ricerca di una risposta alla stessa domanda. Perché non fare qualcosa del genere? In questo modo puoi evitare di toccare il database. E integrato __init__ solo un po 'esteso. Penso che sia molto più semplice di usare i segnali.

class MyModel(models.Model): 
    my_fair_field = .... 

    def __init__(self, *args, **kwargs): 
     super(MyModel, self).__init__(*args, **kwargs) 
     self.__clean_fair_field = self.my_fair_field 

    def save(self, *args, **kwargs): 
     # check if field value changed 
     if self.__clean_fair_field != self.my_fair_field 
       # ...do some work... 

     super(MyModel, self).save(*args, **kwargs) 
Problemi correlati