Tengo un modelo como este:
class FooBar(models.Model):
createtime = models.DateTimeField(auto_now_add=True)
lastupdatetime = models.DateTimeField(auto_now=True)
Quiero sobrescribir los dos campos de fecha para algunas instancias del modelo (que se usan al migrar datos). La solución actual tiene este aspecto:
for field in new_entry._meta.local_fields:
if field.name == "lastupdatetime":
field.auto_now = False
elif field.name == "createtime":
field.auto_now_add = False
new_entry.createtime = date
new_entry.lastupdatetime = date
new_entry.save()
for field in new_entry._meta.local_fields:
if field.name == "lastupdatetime":
field.auto_now = True
elif field.name == "createtime":
field.auto_now_add = True
¿Existe una solución mejor?
auto_now(_add)
Respuestas:
Recientemente me enfrenté a esta situación mientras probaba mi aplicación. Necesitaba "forzar" una marca de tiempo vencida. En mi caso, hice el truco usando una actualización de conjunto de consultas. Me gusta esto:
fuente
update()
comportamiento es exactamente lo que necesitamos.Realmente no puede deshabilitar auto_now / auto_now_add de otra manera de la que ya lo hace. Si necesita la flexibilidad para cambiar esos valores,
auto_now
/auto_now_add
no es la mejor opción. A menudo, es más flexible usardefault
y / o anular elsave()
método para realizar la manipulación justo antes de guardar el objeto.Usando
default
y unsave()
método anulado , una forma de resolver su problema sería definir su modelo de esta manera:En su código, donde desea omitir el cambio automático de última hora de actualización, simplemente use
Si su objeto se guarda en la interfaz de administración o en otros lugares, se llamará a save () sin el argumento skip_lastupdatetime, y se comportará como lo hacía antes con
auto_now
.fuente
auto_now_add
usedefault
en su lugar.datetime.datetime.now
devuelve una fecha y hora ingenua. Para usar una fecha y hora que tenga en cuenta la zona horaria, usefrom django.utils import timezone
ymodels.DateTimeField(default=timezone.now)
consulte docs.djangoproject.com/en/1.9/topics/i18n/timezones/…createtime
campo, no necesita anularsave()
. Basta con sustituirauto_now_add=True
por el equivalentedefault=timezone.now, editable=False, blank=True
(según docs ). Las dos últimas opciones garantizan un comportamiento similar en el administrador.Usé la sugerencia hecha por el autor de la pregunta y creé algunas funciones. Aquí está el caso de uso:
Aquí está la implementación:
Se pueden crear funciones similares para volver a activarlas.
fuente
Clazz._meta.get_field_by_name(field_name)[0]
.También puede utilizar el
update_fields
parámetro desave()
y pasar susauto_now
campos. He aquí un ejemplo:Aquí está la explicación de la documentación de Django: https://docs.djangoproject.com/en/stable/ref/models/instances/#specifying-which-fields-to-save
fuente
auto_now
yauto_now_add
).Seguí el camino del administrador de contexto para la reutilización.
Use así:
Auge.
fuente
Para aquellos que miran esto cuando están escribiendo pruebas, hay una biblioteca de Python llamada freezegun que les permite falsificar la hora, por lo que cuando se
auto_now_add
ejecuta el código, obtiene la hora que realmente desea. Entonces:También se puede usar como decorador; consulte el enlace anterior para obtener documentos básicos.
fuente
Puede anular
auto_now_add
sin código especial.Me encontré con esta pregunta cuando intenté crear un objeto con una fecha particular:
donde
publication_date = models.DateField(auto_now_add=True)
.Así que esto es lo que hice:
Esto se ha anulado con éxito
auto_now_add
.Como solución a más largo plazo, el
save
método de reemplazo es el camino a seguir: https://code.djangoproject.com/ticket/16583fuente
Necesitaba deshabilitar auto_now para un campo DateTime durante una migración y pude hacer esto.
fuente
Llego tarde a la fiesta, pero similar a varias de las otras respuestas, esta es una solución que utilicé durante una migración de base de datos. La diferencia con las otras respuestas es que esto deshabilita todos los campos auto_now para el modelo bajo el supuesto de que realmente no hay razón para tener más de uno de esos campos.
Luego, para usarlo, simplemente puede hacer:
Y atravesará y destruirá todos sus campos
auto_now
yauto_now_add
para todas las clases modelo que pase.fuente
Una versión un poco más limpia del administrador de contexto de https://stackoverflow.com/a/35943149/1731460
Puedes usarlo incluso con Factories (factory-boy)
fuente
copia de Django - Models.DateTimeField - Cambiar dinámicamente el valor auto_now_add
Bueno, pasé esta tarde descubriéndolo y el primer problema es cómo recuperar el objeto del modelo y en qué parte del código. Estoy en restframework en serializer.py, por ejemplo, en
__init__
serializer aún no podría tener el modelo. Ahora en to_internal_value puede obtener la clase modelo, después de obtener el Campo y luego de modificar las propiedades del campo como en este ejemplo:fuente
Necesitaba una solución que funcionara
update_or_create
, llegué a esta solución basada en el código @andreaspelme.El único cambio es que puede configurar la omisión configurando el campo modificado en
skip
no solo pasando kwargskip_modified_update
al método save ().¡Solo
yourmodelobject.modified='skip'
y la actualización se omitirán!fuente