2013-11-15 71 views
3

即時戰鬥與我在這裏的東西我使用django,並且你可以幫助我。從查詢訪問模型方法「def()」Django

我得到了一個帶有date_of_birth字段的帳戶模型,並且我有一個查找年齡的方法。

class Account(AbstractBaseUser, PermissionsMixin): 
    date_of_birth = models.DateField() 
    def age(self): 
     """ 
     Returns the age from the date of birth 
     """ 
     today = datetime.date.today() 
     try: 
      birthday = self.date_of_birth.replace(year=today.year) 
     except ValueError: # raised when birth date is February 29 and the current year is not a leap year 
      birthday = self.date_of_birth.replace(year=today.year, day=self.date_of_birth.day-1) 
     if birthday > today: 
      return today.year - self.date_of_birth.year - 1 
     else: 
      return today.year - self.date_of_birth.year 

我想知道是否可以從這樣的查詢獲得的年齡:

list = Account.objects.filter('account__age__gte', today) 

我試過了,不過我得到這個錯誤:

cannot resolve keyword 'age' into field. Choices are:......

,只顯示我田野。不是方法。\

我感謝您的幫助。

非常感謝。

回答

2

由於自定義方法無法評估其對應的SQL查詢,因此無法直接查詢模型方法。

你有幾個選項,而不是:

在視圖中,計算給出的年齡生育的最早日期。示例24年:

from dateutil.relativedelta import relativedelta 

datetime.date.today() - relativedelta(years=24) 
datetime.date(1989, 11, 15) 

現在,查詢將在date_of_birth字段中。

請注意,dateutil是第三方庫,默認情況下可能無法與您的python一起使用。 (如果你想使用timedelta,你也可以這樣做,因爲datetime.timedelta是python builtin)

另一個選擇(效率稍低一點)是獲取對象查詢集,並使用列表理解過濾不需要的記錄。

qs = Account.objects.all() 

qs = [account for account in qs if account.age() > 24] 

24,顯然只是一個例子。用一些「理智」的價值取而代之。

0

我知道你已經有了這個答案,而且答案是準確的,但我認爲你可能會從將你的年齡方法變成一個屬性中獲益(實際上,我認爲這是什麼是模型屬性的作用,但是我如果我錯了,很樂意在這一點上糾正)。

因此,你可以做這樣的事情:

class Account(AbstractBaseUser, PermissionsMixin): 
    date_of_birth = models.DateField() 
    def _age(self): 
     """ 
     Returns the age from the date of birth 
     """ 
     today = datetime.date.today() 
     ... {value is computed and returned} ... 
    age = property(_age) 

這當然,不解決您的濾波問題;它只是簡化了對待方法,就好像它是一個實例屬性,並且您的SQL查詢仍然需要抓取所有內容,或者按照date_of_birth進行過濾(如果您要做很​​多事情,可能很適合作爲自定義經理)。