Deseo generar un error cuando un usuario intenta eliminar un objeto cuando otros usuarios están activos en la vista update_object. Siento que se necesita algún tipo de mecanismo de bloqueo tipo mutex para eso. ¿Tienes alguna sugerencia?Cuál es la forma más sencilla de bloquear un objeto en Django
Respuesta
Entonces, hay varias formas de hacer lo que está pidiendo. Pero un buen número de ellos no será independiente de la implementación: puede usar bloqueos o bloqueos, pero en realidad solo funcionarán en servidores con un 100% de subprocesos y probablemente no en una implementación de tenedor/precorte.
Eso significa más o menos que la implementación del bloqueo dependerá de usted. Dos ideas:
.lock
archivo en el sistema de archivoslocked
propiedad en su clase del modelo
En ambos casos, se tienen que ajustar manualmente el objeto de bloqueo en la actualización y comprobar contra el borrado . Pruebe algo como:
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()
Esto es de hecho una implementación torpe que tendrá que limpiar. Puede que no se sienta cómodo con el hecho de que se haya creado una región crítica diferente, pero no veo cómo lo hará mucho mejor si utiliza la base de datos como una implementación sin complicar mucho más la implementación. (Una opción sería hacer que los bloqueos separen por completo los objetos. Luego, podría actualizarlos después de que se llame al método save(). Pero no tengo ganas de codificarlo). Si realmente desea usar un bloqueo basado en archivos sistema, eso también resolvería el problema. Si eres una base de datos paranoica, esto podría ser lo que necesites. Algo como:
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
De todos modos, tal vez haya alguna manera de mezclar y combinar estas sugerencias a su gusto?
Sugeriría un simple bloqueo de lectura y escritura, ya que no desea bloquear el acceso simultáneo de los usuarios (solo desde la edición).
Un enfoque general para hacer esto sería crear una función que mantenga un recuento de lectores activos. Cuando necesite escribir en ese objeto, crearía otra función que evitaría que los nuevos lectores tengan acceso (piense en una página de mantenimiento), y posiblemente redirija a los lectores existentes. Una vez que ya no quedan más lectores, completarás tu escritura y luego desbloquearás el objeto.
Dado que su alcance está limitado a las eliminaciones y no a las actualizaciones, una opción sería volver a pensar en la idea de una acción de "eliminar" como "no publicar". Por ejemplo, tomemos el siguiente modelo:
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()
De esta manera, cada vez que se comete una edición, es visible para todos los usuarios ... pero otros siguen siendo libres para eliminar elementos. Una ventaja de esta técnica es que no tiene que tener ninguna lógica adicional para bloquear elementos y presentar una interfaz de usuario diferente para el usuario. Las desventajas son el espacio adicional utilizado en la tabla db y las raras circunstancias en las que un elemento eliminado "mágicamente" reaparece.
(Esto es probablemente sólo un punto de partida. Si tomó este camino, es probable que gustaría hacer una variación en esta idea dependiendo de su caso de uso.)
Me gusta la idea de "no publicar", pero es una solución en lugar de una solución. Lo tendré en cuenta y lo intentaré si no pudiera manejarlo de otra manera. ¡Gracias! – kokeksibir
Dado que la adición de select_for_update, hay una forma simple de adquirir un candado en un objeto, siempre que su base de datos lo admita.postgresql, oracle y mysql, al menos, lo soportan, de acuerdo con los documentos de Django.
código Ejemplo:
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. ¿Cuál es la forma más sencilla de crear una ventana con forma en wxPython?
- 2. ¿Cuál es la forma más sencilla de reproducir un MP3 en WPF?
- 3. ¿Cuál es la forma más sencilla de conectar un dispositivo a un iPad desde una aplicación?
- 4. ¿Cuál es la forma más sencilla de obtener resultados de scripts de Python en la web?
- 5. Forma más sencilla de crear un HWND
- 6. forma más sencilla de repetir un video en un MediaElement
- 7. ¿Cuál es la forma más sencilla de formatear una marca de tiempo de SQL en PHP?
- 8. ¿Cuál es la forma más sencilla de actualizar la plataforma haskell a la última?
- 9. ¿Cuál es la forma más sencilla de convertir char [] a/de tchar [] en C/C++ (ms)?
- 10. ¿Cuál es la forma más sencilla de escribir bibliotecas portátiles cargables dinámicamente en C++?
- 11. ¿Qué significa "lambda" en Python, y cuál es la forma más sencilla de usarlo?
- 12. ¿Cuál es la forma más sencilla de implementar el cifrado en WCF cuando se usa netTcpBinding?
- 13. ¿Cuál es la forma más sencilla de agregar uno a una cadena binaria en Perl?
- 14. ¿Cuál es la forma más sencilla de realizar una solicitud HTTP GET en Perl?
- 15. ¿Cuál es la forma más sencilla de muestrear continuamente desde la línea de entrada utilizando C#
- 16. ¿Cuál es la forma más sencilla de escribir aplicaciones web en Haskell?
- 17. ¿Cuál es la forma más sencilla de ofrecer/consumir servicios web en jython?
- 18. ¿Cuál es la forma más sencilla de intercambiar char en una cadena con Python?
- 19. ¿Cuál es la forma más sencilla de extender una matriz numpy en 2 dimensiones?
- 20. ¿Cuál es la forma más sencilla de mostrar httpServletResponse.sendError (403, "Mi Mensaje") Estado de JSTL
- 21. ¿Cuál es la forma más sencilla de cargar dinero a través de Internet?
- 22. ANTLR ¿Cuál es la forma más sencilla de realizar una gramática dependiente de sangría de pitón?
- 23. ¿Cuál es la forma más sencilla de acceder a mssql con python o ironpython?
- 24. ¿Cuál es la forma correcta para bloquear áreas de código
- 25. ¿Cuál es la forma más sencilla de exportar datos de Excel a Matlab?
- 26. ¿Cuál es la forma más sencilla de llamar a Http GET url usando Delphi?
- 27. ¿Cuál es la forma más sencilla de comparar dos objetos google :: protobuf :: Message entre sí?
- 28. ¿Cuál es la forma más sencilla de convertir cadenas separadas por comas a int []?
- 29. VBScript: ¿Cuál es la forma más sencilla de formatear una cadena?
- 30. ¿Cuál es la forma más sencilla de llamar a Http POST url usando Delphi?
+1 para ejemplos detallados y descripción –
que estaba planeando hacer algo por el estilo, pero en busca de un built-in primera forma. Como no hay ninguna pista de bloqueo incorporado, aceptaré tu respuesta. ¡Gracias! – kokeksibir