[python] Django的auto_now和auto_now_add


Answers

Bah ...沒有足夠的評論來評論......但我想指出,在接受的答案中表達的觀點已經過時了。 根據最近的討論(django bugs #7634#12785 12785),auto_now和auto_now_add不會在任何地方發生,即使您進入原始討論 ,您也會在自定義保存中發現針對RY的強烈爭論(如DRY)方法。

已經提供了一個更好的解決方案(自定義字段類型),但是沒有獲得足夠的動力將其轉化為django。 你可以寫三行(這是Jacob Kaplan-Moss的建議)。

class AutoDateTimeField(models.DateTimeField):
    def pre_save(self, model_instance, add):
        return datetime.datetime.now()

#usage
created_at = models.DateField(default=timezone.now)
updated_at = models.AutoDateTimeField(default=timezone.now)
Question

對於Django 1.1。

我在我的models.py中有這個:

class User(models.Model):
    created = models.DateTimeField(auto_now_add=True)
    modified = models.DateTimeField(auto_now=True)

更新行時,我會得到:

[Sun Nov 15 02:18:12 2009] [error] /home/ptarjan/projects/twitter-meme/django/db/backends/mysql/base.py:84: Warning: Column 'created' cannot be null
[Sun Nov 15 02:18:12 2009] [error]   return self.cursor.execute(query, args)

我的數據庫的相關部分是:

  `created` datetime NOT NULL,
  `modified` datetime NOT NULL,

這是值得擔憂的嗎?

側面的問題:在我的管理工具中,這兩個字段沒有顯示出來。 這是預期的嗎?




我認為最簡單的(也許是最優雅的)解決方案是利用可以將default為可調用的事實。 因此,為了解決管理員對auto_now的特殊處理,您可以像這樣聲明域:

from django.utils import timezone
date_filed = models.DateField(default=timezone.now)

不要使用timezone.now()作為默認值不會更新(也就是說,只有在加載代碼時才設置默認值timezone.now() ,這一點很重要。 如果你發現自己做了很多,你可以創建一個自定義字段。 不過,我覺得這已經很乾了。




如果您使用的是南方,並且您希望默認您將該字段添加到數據庫的日期,則以下是答案:

選擇選項2,然後: datetime.datetime.now()

看起來像這樣:

$ ./manage.py schemamigration myapp --auto
 ? The field 'User.created_date' does not have a default specified, yet is NOT NULL.
 ? Since you are adding this field, you MUST specify a default
 ? value to use for existing rows. Would you like to:
 ?  1. Quit now, and add a default to the field in models.py
 ?  2. Specify a one-off value to use for existing columns now
 ? Please select a choice: 2
 ? Please enter Python code for your one-off default value.
 ? The datetime module is available, so you can do e.g. datetime.date.today()
 >>> datetime.datetime.now()
 + Added field created_date on myapp.User



我今天在工作中需要類似的東西。 缺省值為timezone.now(),但在可從FormMixin繼承的admin和class視圖中都可編輯,所以為了在我的models.py中創建,以下代碼滿足了這些要求:

from __future__ import unicode_literals
import datetime

from django.db import models
from django.utils.functional import lazy
from django.utils.timezone import localtime, now

def get_timezone_aware_now_date():
    return localtime(now()).date()

class TestDate(models.Model):
    created = models.DateField(default=lazy(
        get_timezone_aware_now_date, datetime.date)()
    )

對於DateTimeField,我想從函數中移除.date()並將datetime.date更改為datetime.datetime或更好的timezone.datetime。 我沒有用DateTime試過,只用Date。




根據我已閱讀的內容以及到目前為止使用Django的經驗,auto_now_add是buggy。 我同意jthanism ---重寫正常的保存方法它是乾淨的,你知道發生了什麼。 現在,為了使其乾燥,請創建一個名為TimeStamped的抽像模型:

from django.utils import timezone

class TimeStamped(models.Model):
    creation_date = models.DateTimeField(editable=False)
    last_modified = models.DateTimeField(editable=False)

    def save(self, *args, **kwargs):
        if not self.creation_date:
            self.creation_date = timezone.now()

        self.last_modified = timezone.now()
        return super(TimeStamped, self).save(*args, **kwargs)

    class Meta:
        abstract = True

然後,當你想要一個具有這種時間戳行為的模型時,只需要子類:

MyNewTimeStampyModel(TimeStamped):
    field1 = ...

如果您希望字段顯示在管理員中,則只需刪除editable=False選項




這是值得擔憂的嗎?

不,Django會在保存模型時自動添加它,因此,這是預期的。

側面問題:在我的管理工具中,這兩個字段沒有顯示出來。 這是預期的嗎?

由於這些字段是自動添加的,因此不會顯示。

為了補充上面的內容,正如synack所說的那樣,django郵件列表上有一個關於刪除它的爭論,因為它“設計得不好”,並且是“黑客”

在我的每個模型上寫一個自定義的save()比使用auto_now更加痛苦

顯然,您不必將其寫入每個模型。 您可以將其寫入一個模型並從中繼承其他模型。

但是,由於auto_addauto_now_add在那裡,我會用它們而不是自己寫一個方法。






Related