¿Fecha de creación automática para objetos de formulario modelo Django?

153

¿Cuál es la mejor manera de establecer una fecha de creación para un objeto automáticamente, y también un campo que registrará cuándo se actualizó el objeto por última vez?

modelos.py:

created_at = models.DateTimeField(False, True, editable=False)
updated_at = models.DateTimeField(True, True, editable=False)

views.py:

if request.method == 'POST':
    form = MyForm(request.POST)
    if form.is_valid():
        obj = form.save(commit=False)
        obj.user = request.user
        obj.save()
        return HttpResponseRedirect('obj_list')

Me sale el error:

objects_object.created_at may not be NULL

¿Tengo que configurar este valor manualmente yo mismo? Pensé que ese era el punto de los parámetros pasados ​​a DateTimeField(o son solo valores predeterminados, y desde que lo configuré editable=Falseno se muestran en el formulario, por lo tanto, no se envían en la solicitud y, por lo tanto, no se obtienen poner en el formulario?).

¿Cuál es la mejor manera de hacer esto? Un __init__metodo?

Roger
fuente

Respuestas:

312

Se puede utilizar el auto_nowy auto_now_addopciones de updated_aty created_atrespectivamente.

class MyModel(models.Model):
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)
Manoj Govindan
fuente
31
auto_nowy auto_now_addson considerados malvados, así que trata de evitarlos. Esta respuesta explica por qué y proporciona un mejor enfoque, anulando el save()método.
gregoltsov
3
produce este error:You are trying to add a non-nullable field 'created_at' to gameuser without a default; we can't do that (the database needs something to populate existing rows). Please select a fix: 1) Provide a one-off default now (will be set on all existing rows) 2) Quit, and let me add a default in models.py Select an option: 1 Please enter the default value now, as valid Python The datetime and django.utils.timezone modules are available, so you can do e.g. timezone.now() >>> timezone.now()
Kaleem Ullah
1
elimine las filas en la base de datos, o marque la opción 1 y agregue timezone.now ()
mullerivan
1
Creo que el comentario de @regoltsov no está actualizado en este momento. Usando auto_now_addo auto_nowfunciona bien. Establece el campo antes de guardar el modelo ( github.com/django/django/blob/stable/3.0.x/django/db/models/… ).
Yndolok
26

Bueno, la respuesta anterior es correcta, auto_now_add y auto_now lo harían, pero sería mejor hacer una clase abstracta y usarla en cualquier modelo que requiera created_aty updated_atcampos.

class TimeStampMixin(models.Model):
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)

    class Meta:
        abstract = True

Ahora, en cualquier lugar que desee usar, puede hacer una herencia simple y puede usar la marca de tiempo en cualquier modelo que haga.

class Posts(TimeStampMixin):
    name = models.CharField(max_length=50)
    ...
    ...

De esta manera, puede aprovechar la reutilización orientada a objetos, en Django DRY (no se repita)

Chitrank Dixit
fuente