Quiero activar una acción especial en el método save () de un objeto modelo Django cuando guardo un nuevo registro (sin actualizar un registro existente).
¿La verificación de (self.id! = Ninguno) es necesaria y suficiente para garantizar que el auto registro sea nuevo y no se actualice? ¿Algún caso especial que esto pueda pasar por alto?
django
django-models
MikeN
fuente
fuente
UUIDField pk
Respuestas:
Actualizado: con la aclaración de que
self._state
no es una variable de instancia privada, sino que se llama así para evitar conflictos, la verificaciónself._state.adding
es ahora la forma preferible de verificar.devuelve True dentro de un nuevo objeto Model, a menos que el objeto tenga a
UUIDField
como suprimary_key
.El caso de la esquina por el que debería preocuparse es si hay restricciones de unicidad en los campos que no sean la identificación (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.
fuente
is not
en lugar de!=
en la comprobación de la identidad con elNone
objetomodels.OneToOneField(OtherModel, primary_key=True)
. Creo que necesitas usarself.pk
UUIDField
como clave principal,self.pk
nunca lo esNone
.Una forma alternativa de verificar
self.pk
podemos verificarself._state
el modeloself._state.adding is True
creandoself._state.adding is False
actualizaciónLo obtuve de esta página
fuente
self._state.adding
funciona, pero una advertencia justa de que parece ser siempre igualFalse
si lo está verificando después de llamarsuper(TheModel, self).save(*args, **kwargs)
: github.com/django/django/blob/stable/1.10.x/django/db/models/ ..._state
no es privado; como_meta
, está prefijado con un guión bajo para evitar confusiones con los nombres de los campos. (Observe cómo se usa en la documentación vinculada).is_new = self._state.adding
, entoncessuper(MyModel, self).save(*args, **kwargs)
y luegoif is_new: my_custom_logic()
La comprobación
self.id
asume que esaid
es la clave principal para el modelo. Una forma más genérica sería utilizar el atajo pk .is_new = self.pk is None
fuente
super(...).save()
.La comprobación no
self.pk == None
es suficiente para determinar si el objeto se va a insertar o actualizar en la base de datos.El Django O / RM presenta un truco 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 a un INSERT si el PK es Ninguno).
La razón por la que tiene que hacer esto es porque se le permite establecer la PK cuando se crea un objeto. Aunque no es común cuando tiene una columna de secuencia para la clave primaria, esto no se cumple para otros tipos de campo de clave primaria.
Si realmente quiere saber, debe hacer lo que hace el O / RM y buscar en la base de datos.
Por supuesto, usted tiene un caso específico en su código y de que es muy probable que
self.pk == None
todo lo que necesita saber dice, pero es no una solución general.fuente
UUIDField
como clave principal: la clave no se rellena en el nivel de base de datos, porself.pk
lo que siempre es asíTrue
.Simplemente puede conectarse a la señal post_save que envía un kwargs "creado", si es verdadero, su objeto ha sido insertado.
http://docs.djangoproject.com/en/stable/ref/signals/#post-save
fuente
ATOMIC_REQUESTS
, así que no estoy muy seguro sobre el valor predeterminado.Verificar
self.id
y laforce_insert
bandera.Esto es útil porque su objeto recién creado (self) tiene
pk
valorfuente
Llegué muy tarde a esta conversación, pero me encontré con un problema con el self.pk que se rellena cuando tiene un valor predeterminado asociado.
La forma en que solucioné esto es agregando un campo date_created al modelo
date_created = models.DateTimeField(auto_now_add=True)
Desde aquí puedes ir
created = self.date_created is None
fuente
Para una solución que también funciona incluso cuando tiene una
UUIDField
clave principal (que, como otros han señalado, no esNone
si simplemente anulasave
), puede conectarse a la señal post_save de Django . Agregue esto a sus modelos.py :Esta devolución de llamada bloqueará el
save
método, 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 Django REST para llamadas AJAX. Por supuesto, use de manera responsable y descargue tareas pesadas en una cola de trabajo en lugar de hacer que sus usuarios esperen :)fuente
más bien use pk en lugar de id :
fuente
Es la forma común de hacerlo.
la identificación se dará mientras se guarda por primera vez en el db
fuente
¿Funcionaría esto para todos los escenarios anteriores?
fuente
fuente
Para saber si está actualizando o insertando el objeto (datos), utilícelo
self.instance.fieldname
en su formulario. Defina una función limpia 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
yself.instance.fieldname
comparar con el nuevo valorfuente