utils unique_together example django datetime

django - unique_together - Deshabilitar temporalmente auto_now/auto_now_add



forms datetime django (9)

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 de modelo (utilizadas al migrar datos). La solución actual se ve así:

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

¿Hay una mejor solución?


Fui el gestor de contexto para la reutilización.

@contextlib.contextmanager def suppress_autotime(model, fields): _original_values = {} for field in model._meta.local_fields: if field.name in fields: _original_values[field.name] = { ''auto_now'': field.auto_now, ''auto_now_add'': field.auto_now_add, } field.auto_now = False field.auto_now_add = False try: yield finally: for field in model._meta.local_fields: if field.name in fields: field.auto_now = _original_values[field.name][''auto_now''] field.auto_now_add = _original_values[field.name][''auto_now_add'']

Úselo así:

with suppress_autotime(my_object, [''updated'']): my_object.some_field = some_value my_object.save()

Auge.


Llego tarde a la fiesta, pero, al igual que muchas de las otras respuestas, esta es una solución que utilicé durante la migración de una base de datos. La diferencia con las otras respuestas es que esto deshabilita todos los campos auto_now para el modelo bajo la suposición de que realmente no hay motivo para tener más de un campo.

def disable_auto_now_fields(*models): """Turns off the auto_now and auto_now_add attributes on a Model''s fields, so that an instance of the Model can be saved with a custom value. """ for model in models: for field in model._meta.local_fields: if hasattr(field, ''auto_now''): field.auto_now = False if hasattr(field, ''auto_now_add''): field.auto_now_add = False

Entonces, para usarlo, simplemente puede hacer:

disable_auto_now_fields(Document, Event, ...)

Y auto_now y auto_now_add todos auto_now_add campos auto_now y auto_now_add para todas las clases de modelos que pases.


Necesitaba desactivar auto_now para un campo DateTime durante una migración y pude hacer esto.

events = Events.objects.all() for event in events: for field in event._meta.fields: if field.name == ''created_date'': field.auto_now = False event.save()


Para aquellos que lo están viendo cuando están escribiendo pruebas, hay una biblioteca de Python llamada freezegun que te permite simular el tiempo, de modo que cuando se auto_now_add código auto_now_add , obtiene el tiempo que realmente deseas. Asi que:

from datetime import datetime, timedelta from freezegun import freeze_time with freeze_time(''2016-10-10''): new_entry = FooBar.objects.create(...) with freeze_time(''2016-10-17''): # use new_entry as you wish, as though it was created 7 days ago

También se puede usar como decorador; consulte el enlace anterior para ver los documentos básicos.


Realmente no puedes deshabilitar auto_now / auto_now_add de otra manera que ya lo haces. Si necesita flexibilidad para cambiar esos valores, auto_now / auto_now_add no es la mejor opción. A menudo es más flexible utilizar el default y / o anular el método save() para realizar la manipulación justo antes de que se guarde el objeto.

Usando default método default y el método save() anulado, una forma de resolver su problema sería definir su modelo así:

class FooBar(models.Model): createtime = models.DateTimeField(default=datetime.datetime.now) lastupdatetime = models.DateTimeField() def save(self, *args, **kwargs): if not kwargs.pop(''skip_lastupdatetime'', False): self.lastupdatetime = datetime.datetime.now() super(FooBar, self).save(*args, **kwargs)

En su código, donde desea omitir el cambio automático de lastupdatetime, solo use

new_entry.save(skip_lastupdatetime=True)

Si su objeto se guarda en la interfaz de administración u otros lugares, se invocará a save () sin el argumento skip_lastupdatetime, y se comportará tal como lo hacía antes con auto_now .


Recientemente me he enfrentado a esta situación al probar mi aplicación. Necesitaba "forzar" una marca de tiempo caducada. En mi caso, hice el truco al usar una actualización de queryset. Me gusta esto:

# my model class FooBar(models.Model): title = models.CharField(max_length=255) updated_at = models.DateTimeField(auto_now=True, auto_now_add=True) # my tests foo = FooBar.objects.get(pk=1) # force a timestamp lastweek = datetime.datetime.now() - datetime.timedelta(days=7) FooBar.objects.filter(pk=foo.pk).update(updated_at=lastweek) # do the testing.



Usé la sugerencia hecha por el asker, y creé algunas funciones. Aquí está el caso de uso:

turn_off_auto_now(FooBar, "lastupdatetime") turn_off_auto_now_add(FooBar, "createtime") new_entry.createtime = date new_entry.lastupdatetime = date new_entry.save()

Aquí está la implementación:

def turn_off_auto_now(ModelClass, field_name): def auto_now_off(field): field.auto_now = False do_to_model(ModelClass, field_name, auto_now_off) def turn_off_auto_now_add(ModelClass, field_name): def auto_now_add_off(field): field.auto_now_add = False do_to_model(ModelClass, field_name, auto_now_add_off) def do_to_model(ModelClass, field_name, func): field = ModelClass._meta.get_field_by_name(field_name)[0] func(field)

Se pueden crear funciones similares para volver a activarlas.


copia de Django - Models.DateTimeField - Cambiando dinámicamente el valor de auto_now_add

Bueno, pasé esta tarde averiguando y el primer problema es cómo obtener el objeto modelo y dónde está el código. Estoy en restframework en serializer.py, por ejemplo en __init__ del serializador, todavía no podría tener el modelo. Ahora en to_internal_value puede obtener la clase de modelo, después de obtener el campo y después de modificar las propiedades del campo como en este ejemplo:

class ProblemSerializer(serializers.ModelSerializer): def to_internal_value(self, data): ModelClass = self.Meta.model dfil = ModelClass._meta.get_field(''date_update'') dfil.auto_now = False dfil.editable = True