Tanggal pembuatan otomatis untuk objek bentuk model Django?

153

Apa cara terbaik untuk menetapkan tanggal pembuatan objek secara otomatis, dan juga bidang yang akan merekam saat objek terakhir diperbarui?

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

Saya mendapatkan kesalahan:

objects_object.created_at may not be NULL

Apakah saya harus menetapkan sendiri nilai ini secara manual? Saya pikir itu adalah titik parameter dilewatkan ke DateTimeField(atau apakah mereka hanya default, dan karena saya telah menetapkan editable=Falsemereka tidak ditampilkan pada formulir, maka jangan dikirimkan dalam permintaan, dan karena itu tidak mendapatkan dimasukkan ke dalam formulir?).

Apa cara terbaik untuk melakukan ini? Sebuah __init__metode?

Roger
sumber

Jawaban:

313

Anda dapat menggunakan auto_nowdan auto_now_addpilihan untuk updated_atdan created_atmasing-masing.

class MyModel(models.Model):
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)
Manoj Govindan
sumber
31
auto_nowdan auto_now_adddianggap jahat, jadi cobalah untuk menghindarinya. Jawaban ini menjelaskan mengapa dan memberikan pendekatan yang lebih baik, mengesampingkan save()metode ini.
gregoltsov
3
itu menghasilkan kesalahan ini: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
hapus baris pada databas, atau centang opsi 1 dan tambahkan timezone.now ()
mullerivan
1
Saya pikir komentar @ gregoltsov kedaluwarsa pada saat ini. Menggunakan auto_now_addatau auto_nowberfungsi dengan baik. Ini menetapkan bidang sebelum menyimpan model ( github.com/django/django/blob/stable/3.0.x/django/db/models/… ).
yndolok
26

Baiklah, jawaban di atas benar, auto_now_add dan auto_now akan melakukannya, tetapi akan lebih baik untuk membuat kelas abstrak dan menggunakannya dalam model mana pun yang Anda perlukan created_atdan updated_atisian.

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

    class Meta:
        abstract = True

Sekarang di mana saja Anda ingin menggunakannya, Anda dapat melakukan pewarisan sederhana dan Anda dapat menggunakan timestamp dalam model apa pun yang Anda buat.

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

Dengan cara ini, Anda dapat memanfaatkan usabilitas berorientasi objek, di Django KERING (jangan ulangi sendiri)

Chitrank Dixit
sumber