python - Django的auto_now和auto_now_add




6 Answers

任何設置了auto_now屬性的字段也將繼承editable=False ,因此不會顯示在管理面板中。 過去一直在談論如何使auto_nowauto_now_add參數消失,雖然它們仍然存在,但我覺得使用自定義save()方法會更好。

因此,為了使這項工作正常進行,我建議不要使用auto_nowauto_now_add ,而是定義自己的save()方法以確保只有在未設置id才會更新已created對象(例如,第一次創建項目時),以及每次保存項目時都會更新它。

我已經用我用Django編寫的其他項目完成了同樣的事情,所以你的save()將如下所示:

from django.utils import timezone

class User(models.Model):
    created     = models.DateTimeField(editable=False)
    modified    = models.DateTimeField()

    def save(self, *args, **kwargs):
        ''' On save, update timestamps '''
        if not self.id:
            self.created = timezone.now()
        self.modified = timezone.now()
        return super(User, self).save(*args, **kwargs)

希望這可以幫助!

編輯回應評論:

我堅持重載save()與依賴這些字段參數的原因有兩方面:

  1. 前面提到的起伏與他們的可靠性。 這些參數在很大程度上依賴於Django知道如何處理日期/時間戳字段的每種數據庫的方式,並且似乎在每個版本之間都會中斷和/或更改。 (我認為這是促使他們徹底刪除的呼籲的推動力)。
  2. 事實上,他們只能在DateField,DateTimeField和TimeField上工作,並且通過使用這種技術,您可以在每次保存項目時自動填充任何字段類型。
  3. 使用django.utils.timezone.now()datetime.datetime.now() ,因為它會根據settings.USE_TZ返回一個TZ-aware或naive datetime.datetime對象。

為了解決OP看到錯誤的原因,我不太清楚,但它看起來像created甚至沒有填充,儘管有auto_now_add=True 。 對我來說,它突出了一個錯誤,並在我上面的小列表中強調了項目#1: auto_nowauto_now_add最好是片狀的。

對於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,

這是值得擔憂的嗎?

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




談論一個側面問題:如果你想在管理中看到這些字段(儘管你不能編輯它),你可以添加readonly_fields到你的管理類。

class SomeAdmin(ModelAdmin):
    readonly_fields = ("created","modified",)

那麼,這只適用於最新的Django版本(我相信1.3以上)




我找到了一個解決方案

如果我有一個模型類,如:

class MyModel(models.Model):
    time = models.DatetimeField(auto_now_add=True)
    time.editable = True

然後,此字段將顯示在我的管理員更改頁面中




你可以使用timezone.now()創建和auto_now修改:

from django.utils import timezone
class User(models.Model):
    created = models.DateTimeField(default=timezone.now())
    modified = models.DateTimeField(auto_now=True)

如果您使用自定義主鍵而不是默認auto- increment int ,則auto_now_add會導致錯誤。

這裡是Django默認的帶有auto_nowauto_now_add DateTimeField.pre_save的代碼:

def pre_save(self, model_instance, add):
    if self.auto_now or (self.auto_now_add and add):
        value = timezone.now()
        setattr(model_instance, self.attname, value)
        return value
    else:
        return super(DateTimeField, self).pre_save(model_instance, add)

我不確定參數add是什麼。 我希望它會有這樣的事情:

add = True if getattr(model_instance, 'id') else False

新記錄不會有attr id ,所以getattr(model_instance, 'id')將返回False將導致不在該字段中設置任何值。




至於你的管理員顯示,請參閱此答案 。

注意:默認情況下,auto_now和auto_now_add被設置為editable = False,這就是適用的原因。




在Django 1.4.1中, auto_now=True並不適用於我,但下面的代碼保存了我。 它適用於可識別時區的日期時間。

from django.utils.timezone import get_current_timezone
from datetime import datetime

class EntryVote(models.Model):
    voted_on = models.DateTimeField(auto_now=True)

    def save(self, *args, **kwargs):
        self.voted_on = datetime.now().replace(tzinfo=get_current_timezone())
        super(EntryVote, self).save(*args, **kwargs)



Related