用于计算字段的Profile的Django自定义管理器

时间:2016-03-31 09:01:26

标签: python django

我想为用户个人资料添加计算字段。 我添加了一个自定义管理器:

class ProCalcManager(models.Manager):

    use_for_related_fields = True

    def get_queryset(self):
        result = super(ProCalcManager, self).get_queryset()
        result = result.extra(
        select={'pro': "(start_date, INTERVAL '10 days') OVERLAPS"
                       "(CURRENT_TIMESTAMP, INTERVAL '1 days')"}
        )
        return result

class Profile (models.Model):

    objects = ProCalcManager()
    default_manager = ProCalcManager()

    start_date = models.DateTimeField()

当我使用时:Users.objects.first().profile.pro结果为True,但Users.objects.filter(profile__pro=True)结果为{TypeError} Related Field got invalid lookup: pro

如何在用户个人资料中添加用于添加计算字段“pro”的其他更新查询集,以便在过滤器中使用它?

1 个答案:

答案 0 :(得分:0)

您所做的只是计算日期,然后确定用户是否为pro。您可以使用简单的.filter()来实现它,而不是为计算和过滤两者编写sql语句而烦恼。

首先,不要覆盖get_queryset()方法,而是在模型中添加名为pro的属性。

@property
def pro(self):
    calculated_end_date = tz.now() + tz.timedelta(days=-10)
    return self.start_date > calculated_end_date

通过这样做,您将能够访问配置文件的pro属性。就像你使用额外的一样。

>>> p = Profile.objects.first()
>>> p.pro
>>> True

然后,为了能够过滤其pro值的配置文件,您可以为than编写一个queryset,并将其用作管理器。像这样:

class ProCalcQuerySet(models.QuerySet):

    def is_pro(self, value=True):
        calculated_end_date = tz.now() + tz.timedelta(days=-10)
        if value:
            lookup = 'gte'
        else:
            lookup = 'lt'
        filter_dict = {
            'start_date__' + lookup: calculated_end_date
        }
        return self.filter(**filter_dict)

然后使用此查询集作为管理员在模型对象中访问它

class Profile (models.Model):

    objects = ProCalcQuerySet.as_manager()
    default_manager = ProCalcQuerySet.as_manager()

然后你可以像这样使用它:

In [2]: Profile.objects.is_pro(value=True)
Out[2]: [<Profile: Profile object>]

In [3]: Profile.objects.is_pro()
Out[3]: [<Profile: Profile object>]

In [4]: Profile.objects.is_pro(False)
Out[4]: []

In [8]: Profile.objects.is_pro().first().pro
Out[8]: True