2016-07-07 70 views
5

我在從Django的1.8.2我的項目升級到1.9.7的過程中,我得到這樣的警告:Django的:timezone.now VS timezone.now()

WARNINGS: 
my_app.my_model.date_available: (fields.W161) Fixed default value provided. 
HINT: It seems you set a fixed date/time/datetime value as default for this field. This may not be what you want. 
If you want to have the current date as default, use `django.utils.timezone.now 

這裏的行從程序my_app/models.py:

from django.utils import timezone 
... 
class my_model(models.Model): 
    ... 
    datetime_released = models.DateTimeField(default=timezone.now()) 

如果我刪除了括號,而使用:

datetime_released = models.DateTimeField(default=timezone.now) 

Django的警告消失。兩者有什麼區別?


在我的項目的另一個領域,我使用timezone.now()在查詢集過濾器:

def date_available(self): 
     return self.filter(date_available__lte = timezone.now()) 

在這裏,如果我刪除括號,拋出一個錯誤:

TypeError: expected string or buffer


我可以通過根據需要添加/刪除括號來獲得這兩項工作d,但timezone.now()timezone.now之間的區別是什麼以及它們在這些情況下爲什麼會導致警告/錯誤?

+0

類型(now())重新運行日期時間對象。現在重新運行該方法 – gtalarico

回答

9

在python中,一切都是一個對象,包括函數。這意味着可以影響的功能的變量:

>>> from django.utils import timezone 
>>> foo = timezone.now 
>>> foo 
<function django.utils.timezone.now> 
>>> foo() 
datetime.datetime(2016, 7, 7, 9, 11, 6, 489063) 

函數是一個可調用對象:

>>> callable(foo) 
True 
>>> callable(foo()) 
False 

default接收一個可調用的,可調用每次請求一個缺省值時間被調用。

另一方面,當您在設置default之前撥打timezone.now()時,該值將被給定並固定。作爲提醒,下面的行執行只能在服務器一次啓動時,因爲它是一個類屬性:

datetime_released = models.DateTimeField(default=timezone.now()) 

因此timezone.now()只執行一次。通過可調用timezone.now可以在需要時重新計算值。

8

區別在於timezone.now是在運行時執行的可調用函數,timezone.now()則返回該函數的輸出。

對於models.DateTimeField,您需要使用可調用函數。更妙的是,剛剛成立auto_now_add它可以實現這個要求:

datetime_released = models.DateTimeField(auto_now_add=True) 

在另一方面,過濾器不接受一個可調用的 - 它需要一個值。因此,在將此參數作爲參數傳遞給過濾器時,您必須評估timezone.now()

+0

這裏值得一提的是,當你傳遞'timezone.now()'時,你在django啓動時有效地傳遞了該函數的輸出(這是它得到評估),而當你傳遞'timezone.now'時,你傳遞的是被django懶散評估的函數對象。 – samu

1

now()在模型加載時得到執行,並在加載時返回一個datetime對象/時間字符串。 (因此Django的警告!) (模型文件,如果完全執行了服務器啓動時)

現在將通過現在的方法,只有當類/模型被實例化將得到執行,在創建時間戳正確的時間(正確的方式,以及大多數人試圖達到的目標)。

在過濾器示例中,僅在調用過濾器函數時纔會調用它。 如果你沒有執行(now())並且會提供方法,並且永遠不會生成所需的datetime對象。 (錯誤,期望一個字符串,得到,別的東西)

1

self.filter(date_available__lte = timezone.now())你想根據當前時間查詢數據庫。所以你需要它的字符串格式。

datetime_released = models.DateTimeField(default=timezone.now)您要默認爲當前時間。所以你不能在那裏有一個字符串。而是提供可以返回當前時間的功能。

相關問題