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 pkRespuestas:
Actualizado: con la aclaración de que
self._stateno es una variable de instancia privada, sino que se llama así para evitar conflictos, la verificaciónself._state.addinges ahora la forma preferible de verificar.devuelve True dentro de un nuevo objeto Model, a menos que el objeto tenga a
UUIDFieldcomo 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 noten lugar de!=en la comprobación de la identidad con elNoneobjetomodels.OneToOneField(OtherModel, primary_key=True). Creo que necesitas usarself.pkUUIDFieldcomo clave principal,self.pknunca lo esNone.Una forma alternativa de verificar
self.pkpodemos verificarself._stateel modeloself._state.adding is Truecreandoself._state.adding is FalseactualizaciónLo obtuve de esta página
fuente
self._state.addingfunciona, pero una advertencia justa de que parece ser siempre igualFalsesi lo está verificando después de llamarsuper(TheModel, self).save(*args, **kwargs): github.com/django/django/blob/stable/1.10.x/django/db/models/ ..._stateno 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.idasume que esaides la clave principal para el modelo. Una forma más genérica sería utilizar el atajo pk .is_new = self.pk is Nonefuente
super(...).save().La comprobación no
self.pk == Nonees 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 == Nonetodo lo que necesita saber dice, pero es no una solución general.fuente
UUIDFieldcomo clave principal: la clave no se rellena en el nivel de base de datos, porself.pklo 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.idy laforce_insertbandera.Esto es útil porque su objeto recién creado (self) tiene
pkvalorfuente
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 Nonefuente
Para una solución que también funciona incluso cuando tiene una
UUIDFieldclave principal (que, como otros han señalado, no esNonesi 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
savemé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.fieldnameen 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.instanceyself.instance.fieldnamecomparar con el nuevo valorfuente