tutorial - En un método de guardado personalizado modelo django(), ¿cómo debe identificar un nuevo objeto?
modelos en django (11)
Quiero activar una acción especial en el método save () de un objeto modelo de Django cuando estoy guardando un nuevo registro (sin actualizar un registro existente).
¿Es necesario y suficiente el control de (self.id! = None) para garantizar que el auto registro sea nuevo y no se actualice? ¿Algún caso especial que esto pueda pasar por alto?
Es la forma común de hacerlo.
la identificación se dará mientras se guarda la primera vez en el archivo db
La comprobación de self.id
supone que id
es la clave principal para el modelo. Una forma más genérica sería usar el atajo de teclado pk .
is_new = self.pk is None
La comprobación de self.pk == None
no es suficiente para determinar si el objeto se insertará o actualizará en la base de datos.
El Django O / RM presenta un hack especialmente desagradable que es básicamente para verificar si hay algo en la posición PK y, de ser así, hacer una ACTUALIZACIÓN, de lo contrario hacer un INSERT (esto se optimiza para un INSERT si el PK es Ninguno).
La razón por la que tiene que hacer esto es porque puede establecer el PK cuando se crea un objeto. Aunque no es común donde tiene una columna de secuencia para la clave principal, esto no se aplica a otros tipos de campo de clave principal.
Si realmente quiere saber, tiene que hacer lo que O / RM hace y buscar en la base de datos.
Por supuesto que tiene un caso específico en su código y para eso es bastante probable que self.pk == None
le diga todo lo que necesita saber, pero no es una solución general.
Llego muy tarde a esta conversación, pero me encontré con un problema con el self.pk que se llena cuando tiene un valor predeterminado asociado.
La forma en que solucioné esto es agregar un campo date_created al modelo
date_created = models.DateTimeField(auto_now_add=True)
Desde aquí puedes ir
created = self.date_created is None
Manera alternativa de verificar self.pk
podemos verificar self._state
del modelo
self._state.adding is True
crea self._state.adding is True
self._state.adding is False
updating
Lo obtuve de esta page
Para saber si está actualizando o insertando el objeto (datos), use self.instance.fieldname
en su formulario. Defina una función de limpieza en su formulario y verifique si la entrada del valor actual es la misma que la anterior, de lo contrario, la está actualizando.
self.instance
y self.instance.fieldname
comparan con el nuevo valor
Para una solución que también funciona incluso cuando tienes un UUIDField
como clave principal (que, como otros han notado, no es None
si solo anulas el save
), puedes conectarte a la señal de post_save de Django. Agregue esto a su models.py :
from django.db.models.signals import post_save
from django.dispatch import receiver
@receiver(post_save, sender=MyModel)
def mymodel_saved(sender, instance, created, **kwargs):
if created:
# do extra work on your instance, e.g.
# instance.generate_avatar()
# instance.send_email_notification()
pass
Esta devolución de llamada bloqueará el método de save
, por lo que puede hacer cosas como notificaciones de activación o actualizar el modelo aún más antes de que su respuesta se envíe por cable, ya sea que esté utilizando formularios o el marco REST Django para llamadas AJAX. Por supuesto, utilícelo de forma responsable y descargue tareas pesadas en una cola de trabajos en lugar de mantener a los usuarios esperando :)
Podrías simplemente conectarte a la señal post_save que envía un kwargs "creado", si es verdadero, tu objeto ha sido insertado.
http://docs.djangoproject.com/en/stable/ref/signals/#post-save
Verifique self.id
y el indicador force_insert
.
if not self.pk or kwargs.get(''force_insert'', False):
self.created = True
# call save method.
super(self.__class__, self).save(*args, **kwargs)
#Do all your post save actions in the if block.
if getattr(self, ''created'', False):
# So something
# Do something else
Esto es útil porque su objeto recién creado (self) tiene su valor pk
más bien use pk en lugar de id :
if not self.pk:
do_something()
self.pk is None:
devuelve True dentro de un nuevo objeto Model, a menos que el objeto tenga un UUIDField
como primary_key
.
El caso de esquina del que podría tener que preocuparse es si existen restricciones de exclusividad en campos distintos al ID (por ejemplo, índices únicos secundarios en otros campos). En ese caso, aún podría tener un nuevo registro en la mano, pero no podrá guardarlo.