วันที่สร้างอัตโนมัติสำหรับวัตถุรูปแบบโมเดล Django หรือไม่


153

วิธีที่ดีที่สุดในการตั้งวันที่สร้างสำหรับวัตถุโดยอัตโนมัติคืออะไรและเขตข้อมูลที่จะบันทึกเมื่อวัตถุได้รับการปรับปรุงล่าสุด

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

ฉันได้รับข้อผิดพลาด:

objects_object.created_at may not be NULL

ฉันต้องตั้งค่านี้ด้วยตนเองหรือไม่? ฉันคิดว่าเป็นจุดของพารามิเตอร์ที่ส่งผ่านไปยังDateTimeField(หรือเป็นเพียงค่าเริ่มต้นและเนื่องจากฉันได้ตั้งค่าไว้editable=Falseพวกเขาจะไม่ปรากฏในแบบฟอร์มดังนั้นจึงไม่ได้รับการส่งในคำขอและดังนั้นจึงไม่ได้รับ ใส่ลงในแบบฟอร์มหรือไม่?)

วิธีที่ดีที่สุดในการทำเช่นนี้คืออะไร? __init__วิธี?

คำตอบ:


312

คุณสามารถใช้auto_nowและauto_now_addตัวเลือกสำหรับupdated_atและcreated_atตามลำดับ

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

31
auto_nowและauto_now_addถูกมองว่าเป็นสิ่งชั่วร้ายดังนั้นพยายามหลีกเลี่ยงพวกมัน คำตอบนี้อธิบายถึงสาเหตุและให้วิธีการที่ดีกว่าโดยแทนที่save()วิธีการนั้น
gregoltsov

3
มันสร้างข้อผิดพลาดนี้: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
ลบแถวใน databas หรือตรวจสอบตัวเลือก 1 และเพิ่ม timezone.now ()
mullerivan

1
Django REST กรอบดูเหมือนจะคิดว่านี่เป็นวิธีการที่ดี
ฟีนิกซ์

1
ฉันคิดว่าความคิดเห็นของ @ gregoltsov ล้าสมัย ณ จุดนี้ ใช้auto_now_addหรือauto_nowทำงานได้ดี ตั้งค่าฟิลด์ก่อนบันทึกโมเดล ( github.com/django/django/blob/stable/3.0.x/django/db/models/ ...... )
yndolok

26

ดีคำตอบข้างต้นถูกต้องauto_now_addและauto_nowจะทำมัน แต่มันจะดีกว่าที่จะทำให้ระดับนามธรรมและใช้ในรูปแบบใด ๆ ที่คุณต้องการcreated_atและupdated_atสาขา

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

    class Meta:
        abstract = True

ตอนนี้ทุกที่ที่คุณต้องการใช้คุณสามารถทำสิ่งสืบทอดง่ายๆและคุณสามารถใช้การประทับเวลาในรูปแบบใดก็ได้ที่คุณทำ

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

ด้วยวิธีนี้คุณสามารถใช้ประโยชน์จากความสามารถในการนำกลับมาใช้ใหม่ได้ใน Django DRY (อย่าทำซ้ำตัวเอง)

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.