Data de criação automática para objetos de formulário do modelo Django?

153

Qual é a melhor maneira de definir automaticamente uma data de criação para um objeto e também um campo que registrará a última atualização do objeto?

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

Eu recebo o erro:

objects_object.created_at may not be NULL

Preciso definir manualmente esse valor pessoalmente? Eu pensei que era o ponto dos parâmetros passados ​​para DateTimeField(ou eles são apenas padrões, e desde que eu definai, editable=Falseeles não são exibidos no formulário, portanto, não são enviados na solicitação e, portanto, não são colocar no formulário?).

Qual é a melhor maneira de fazer isso? Um __init__método?

Roger
fonte

Respostas:

312

Você pode usar o auto_nowe auto_now_addopções para updated_ate created_atrespectivamente.

class MyModel(models.Model):
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)
Manoj Govindan
fonte
31
auto_nowe auto_now_addsão considerados maus, então tente evitá-los. Esta resposta explica o porquê e fornece uma abordagem melhor, substituindo o save()método.
precisa saber é o seguinte
3
que produz este erro: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
excluir as linhas nas databas, ou a opção 1 verificar e adicionar timezone.now ()
mullerivan
1
Acho que o comentário de @ gregoltsov está desatualizado neste momento. Usando auto_now_addou auto_nowfunciona muito bem. Ele define o campo antes de salvar o modelo ( github.com/django/django/blob/stable/3.0.x/django/db/models/… ).
yndolok
26

Bem, a resposta acima está correto, auto_now_add e auto_now iria fazê-lo, mas seria melhor fazer uma classe abstrata e usá-lo em qualquer modelo que você precisa created_ate 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

Agora, em qualquer lugar que você quiser usá-lo, você pode fazer uma herança simples e usar o registro de data e hora em qualquer modelo que desejar.

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

Dessa forma, você pode aproveitar a reutilização orientada a objetos, no Django DRY (não se repita)

Chitrank Dixit
fonte