Data di creazione automatica per gli oggetti modulo modello Django?


153

Qual è il modo migliore per impostare automaticamente una data di creazione per un oggetto e anche un campo che registrerà l'ultimo aggiornamento dell'oggetto?

models.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')

Ottengo l'errore:

objects_object.created_at may not be NULL

Devo impostare manualmente questo valore da solo? Ho pensato che fosse il punto dei parametri passati a DateTimeField(o sono solo valori predefiniti, e poiché ho impostato editable=Falsenon vengono visualizzati nel modulo, quindi non vengono inviati nella richiesta e quindi non ottengono messo nella forma?).

Qual è il modo migliore per farlo? Un __init__metodo?

Risposte:


313

È possibile utilizzare l' auto_nowe auto_now_addopzioni per updated_ate created_at, rispettivamente.

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

31
auto_nowe auto_now_addsono considerati malvagi, quindi cerca di evitarli. Questa risposta spiega perché e fornisce un approccio migliore, ignorando il save()metodo.
Gregregtsov,

3
produce questo errore: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
elimina le righe sulle banche dati o seleziona l'opzione 1 e aggiungi timezone.now ()
mullerivan


1
Penso che il commento di @gregoltsov non sia aggiornato a questo punto. Usare auto_now_addo auto_nowfunziona bene. Imposta il campo prima di salvare il modello ( github.com/django/django/blob/stable/3.0.x/django/db/models/… ).
yndolok,

26

Bene, la risposta sopra è corretta, auto_now_add e auto_now lo farebbero, ma sarebbe meglio creare una classe astratta e usarla in qualsiasi modello in cui si richiedono created_ate updated_atcampi.

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

    class Meta:
        abstract = True

Ora, ovunque tu voglia usarlo, puoi fare una semplice eredità e puoi usare il timestamp in qualsiasi modello tu faccia.

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

In questo modo, puoi sfruttare la riusabilità orientata agli oggetti, in Django DRY (non ripeterti)

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.