2013-08-28 14 views
5

Diciamo che ho un modello con una e-mail campo unico:Django bloccaggio tra pulito() e save()

class MyModel: 

    email = models.EmailField(unique=True) 

    def save(self): 
     .... # save model 

    def clean(self): 
     .... # validate model, make sure email doesn't already exist. 

Di solito se un browser invia un modulo con la posta elettronica è un valore che già esiste, sarebbe genera un errore Validation, a causa della convalida del campo modulo del modello.

Se due browser invia la stessa e-mail allo stesso tempo, con l'e-mail come valore che non esiste ancora, almeno una delle richieste avrà esito positivo salvando una riga nel database. L'altra richiesta, se arriva abbastanza a lungo dopo la prima, sarà trattata normalmente - con un ValidationError sollevato che dice che l'e-mail esiste già. Ma se arriva quasi alla stessa ora del primo, allora il clean() avrà successo - l'e-mail non esiste ancora, ma nel momento in cui viene eseguito il metodo save(), la riga della prima richiesta sarebbe stata salvata. In quest'ultimo caso, verrà invece generato un errore IntegrityError e il server restituirebbe un errore Internal Server 500, il che è indesiderabile.

Come si può prevenire questo ultimo scenario? Transazioni di database?

risposta

2

Solo per utilizzare le transazioni del database Django in questo caso non sarà sufficiente. Quello che si vuole fare quando si crea un nuovo modello è utilizzare il blocco della tabella del database insieme alla transazione. Ma django non ha ancora API per bloccare le tabelle, quindi dovrai usare SQL raw per eseguire un lock di tabella per il tuo database riguardo al suo tipo.

Se si utilizza PostgreSQL: ecco un esempio perfetto: http://www.caktusgroup.com/blog/2009/05/26/explicit-table-locking-with-postgresql-and-django/

Se hai meno di qualche altro db allora si dovrà indagare su come eseguire blocco di tabella.

Cheers! Non dimenticare di votare questa risposta se ritieni che sia utile;)

1

Mentre il caso d'uso è leggermente diverso, potresti leggere this old answer di Alex Martelli sull'approccio "concorrenza ottimistica".

Problemi correlati