Desidero generare un errore quando un utente tenta di eliminare un oggetto quando alcuni altri utenti sono attivi nella vista update_object. Sento che per questo è necessaria una sorta di meccanismo di blocco simile a un mutex. Hai qualche suggerimento?Qual è il modo più semplice per bloccare un oggetto in Django
risposta
Quindi, ci sono una manciata di modi per fare quello che stai chiedendo. Ma un buon numero di questi non sarà indipendente dall'implementazione: potresti usare lock o rlocks, ma funzioneranno solo su server con il 100% thread e probabilmente non funzionano affatto in un'implementazione fork/pre-fork.
Che più o meno significa che l'implementazione del blocco dipenderà da voi. Due idee:
.lock
file nel file systemlocked
proprietà nella classe del modello
In entrambi i casi, è necessario impostare manualmente l'oggetto di blocco aggiornata e verificare contro di essa su Elimina . Prova qualcosa del tipo:
def safe_update(request,model,id):
obj = model.objects.get(id)
if obj.locked:
raise SimultaneousUpdateError #Define this somewhere
else:
obj.lock()
return update_object(request,model,id)
# In models file
class SomeModel(models.Model):
locked = models.BooleanField(default = False)
def lock(self):
self.locked = True
super(models.Model,self).save()
def save(self):
# overriding save because you want to use generic views
# probably not the best idea to rework model code to accomodate view shortcuts
# but I like to give examples.
self.locked = False
# THIS CREATES A DIFFERENT CRITICAL REGION!
super(models.Model,self).save()
Questa è davvero un'implementazione maldestra che dovrai pulire. Potresti non sentirti a tuo agio con il fatto che sia stata creata una regione critica diversa, ma non vedo come andrai molto meglio se utilizzi il database come un'implementazione senza rendere l'implementazione molto più complicata. (Un'opzione potrebbe essere quella di rendere i blocchi completamente separati da oggetti, quindi è possibile aggiornarli dopo che è stato chiamato il metodo save(). Ma non mi va di codificarlo.) Se si vuole veramente usare un blocco basato su file sistema, che risolverebbe anche il problema. Se sei paranoico al database, questa potrebbe essere la cosa giusta per te. Qualcosa di simile:
class FileLock(object):
def __get__(self,obj):
return os.access(obj.__class__+"_"+obj.id+".lock",os.F_OK)
def __set__(self,obj,value):
if not isinstance(value,bool):
raise AttributeError
if value:
f = open(obj.__class__+"_"+obj.id+".lock")
f.close()
else:
os.remove(obj.__class__+"_"+obj.id+".lock")
def __delete__(self,obj):
raise AttributeError
class SomeModel(models.Model):
locked = FileLock()
def save(self):
super(models.Model,self).save()
self.locked = False
In ogni caso, forse c'è un modo per combinare questi suggerimenti secondo i propri gusti?
Suggerirei un semplice blocco di lettura/scrittura, poiché non si desidera impedire agli utenti di accedere all'oggetto contemporaneamente (solo dalla modifica).
Un approccio generale a tale scopo sarebbe quello di creare una funzione che mantenga il conteggio dei lettori attivi. Quando hai bisogno di scrivere su quell'oggetto, crei un'altra funzione che impedisce ai nuovi lettori di accedere (pensa a una pagina di manutenzione) e, eventualmente, reindirizza i lettori esistenti. Una volta che non ci sono più lettori, completerai la scrittura, quindi sbloccherai l'oggetto.
Poiché il tuo ambito di applicazione è limitato alle eliminazioni e non anche agli aggiornamenti, un'opzione potrebbe essere quella di ripensare l'idea di una "eliminazione" come un'azione di "non pubblicazione". Per esempio, prendete il seguente modello:
class MyManager(models.Manager):
def get_query_set(self):
super(MyManager, self).get_query_set().filter(published=True)
class MyModel(models.Model):
objects = MyManager()
published = models.BooleanField(default=True)
... your fields ...
def my_delete(self):
self.published = False
super(MyModel, self).save()
def save(self):
self.published = True
super(MyModel, self).save()
In questo modo, ogni volta che una modifica è impegnata, è visibile a tutti gli utenti ... ma altri sono ancora liberi di eliminare gli elementi. Un vantaggio di questa tecnica è che non devi avere alcuna logica aggiuntiva per bloccare gli oggetti e presentare una UI diversa all'utente. Gli svantaggi sono lo spazio extra utilizzato nella tabella db e le rare circostanze in cui un elemento eliminato "magicamente" riappare.
(Questo è probabilmente solo un punto di partenza. Se hai preso questa strada, che ci probabilmente vuole fare una variante di questa idea a seconda del caso d'uso.)
Mi piace l'idea di "non pubblicare", ma è un lavoro piuttosto che una soluzione. Lo terrò a mente e provalo se altro non riuscirò a gestirlo con altro. Grazie! – kokeksibir
Dal momento che l'aggiunta di select_for_update, c'è un modo semplice per acquisire un blocco su un oggetto, a condizione che il database lo supporti.postgresql, oracle e mysql, almeno, lo supportano, secondo i documenti di Django.
codice Esempio:
import time
from django.contrib.auth import get_user_model
from django.db import transaction
User = get_user_model()
target_user_pk = User.objects.all()[0].pk
with transaction.atomic():
print "Acquiring lock..."
to_lock = User.objects.filter(pk=target_user_pk).select_for_update()
# Important! Queryset evaluation required to actually acquire the lock.
locked = to_lock[0]
print locked
while True:
print "sleeping {}".format(time.time())
time.sleep(5)
- 1. Qual è il modo migliore per bloccare più std :: mutex?
- 2. Qual è il modo più semplice per clonare in profondità (copiare) un oggetto Scala mutabile?
- 3. Il modo più semplice per avere un sito django multilingue?
- 4. Qual è il modo più semplice per mantenere oggetti java?
- 5. C#: qual è il modo più semplice per sottrarre tempo?
- 6. Qual è il modo più semplice per sottrarre un mese da una data in Python?
- 7. Qual è il modo più semplice per convertire questo documento XML nel mio oggetto?
- 8. Qual è il modo più semplice per inserire un indice in un controllo ripetitore in .NET?
- 9. Qual è il modo Pythonic per implementare un semplice FSM?
- 10. Qual è il modo corretto per bloccare zone di codice
- 11. In Chrome, qual è il modo più semplice per visualizzare il tipo mime di un documento?
- 12. Qual è il modo più semplice in Javascript per ottenere solo il segno di un numero?
- 13. Qual è il modo più semplice per avvolgere un file .aac grezzo in un contenitore .m4a
- 14. Qual è il modo più semplice per accedere a un microfono di un computer in Python?
- 15. Qual è il modo più semplice per combinare più raccolte in uno stream in Java?
- 16. Qual è il modo più semplice per far funzionare matplotlib in OSX in un ambiente virtuale?
- 17. Qual è il modo migliore per creare un oggetto modello in Django?
- 18. Qual è il modo più semplice per ordinare un EF4 EntityCollection <T>?
- 19. Qual è il modo più semplice/veloce per scoprire quando è stato creato un ramo git?
- 20. Il modo più semplice per forzare un arresto in Swift
- 21. Qual è il modo più semplice per esportare un database SQLServer 2000 in XML?
- 22. Qual è il modo più semplice per rimuovere tutti gli attributi da un XML in C#?
- 23. Qual è il modo più semplice per ottenere questi dati in un Dataframe Pandas?
- 24. Qual è il modo più semplice ed efficace per creare un heap minimo in Scala?
- 25. Qual è il modo più semplice per creare un iterabile vuoto usando yield in Python?
- 26. Qual è il modo più semplice per estendere un array numpy in 2 dimensioni?
- 27. Qual è il modo più semplice per colmare le lacune in un elenco di numeri?
- 28. Qual è il modo più semplice per riprodurre un campione sonoro in Haskell?
- 29. Qual è il modo più semplice per eseguire gli script Python in un server cloud?
- 30. Qual è il modo più semplice per usare reify (ottenere un AST di) un'espressione in Scala?
+1 per esempi dettagliati e descrizione –
Avevo intenzione di fare qualcosa di simile, ma alla ricerca di un built-in modo prima. Dato che non c'è traccia di serratura integrata, accetterò la tua risposta. Grazie! – kokeksibir