从查询Django访问模型方法“def()”

时间:2013-11-15 15:23:19

标签: python django

我在这里与某些东西打架我正在使用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)

我已经尝试但是我收到了这个错误:

  

无法将关键字'age'解析为字段。选择是:......

只显示我的字段。不是方法。\

感谢您的帮助。

非常感谢。

2 个答案:

答案 0 :(得分: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内置的)

另一个选项(效率稍差)是获取对象查询集,并使用列表推导来过滤掉不需要的记录。

qs = Account.objects.all()

qs = [account for account in qs if account.age() > 24]
24,显然只是一个例子。用一些“理智”的价值取而代之。

答案 1 :(得分: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过滤(如果你要做很多事情,可能会很好包括作为自定义经理)。