自定义django过滤器模型字段

时间:2016-10-24 07:31:34

标签: python django filter

我有以下型号

class some_model(models.Model):
    some_date = models.DateTimeField()
    hours = models.IntegerField()

获取当前日期

temp_date = datetime.datetime.now()

现在我希望过滤django字段,就像这样

filter_date = some_date + add timedelta(hours)

然后在django过滤器中使用filter_date

some_model.objects.filter(filter_date__gte = temp_date)

以上查询可能在django?

3 个答案:

答案 0 :(得分:3)

另一种更优雅的方法是创建数据库功能。

假设我们拥有下面描述的模型。我们的目标是过滤之前结束的所有对象。

from django.db import models

class SomeModel(models.Model):
    date_start = models.DateTimeField()
    duration = models.FloatField()

DataBase函数实现:

from django.db.models.expressions import Func
from django.db.models import DateTimeField


class Interval(Func):
    function = 'INTERVAL'
    template = "(%(expressions)s * %(function)s '1 %(phylum)s')"

    def __init__(self, expression, phylum, **extra):
        output_field = extra.pop('output_field', DateTimeField())
        super(Interval, self).__init__(expression, output_field=output_field, phylum=phylum, **extra)

并使用它。作为Interval函数的第一个参数,您可以传递为F('field_name')或Value()或一些Python对象。作为第二个参数,它可以是:'秒','分钟','小时','天'。

objs = (SomeModel.objects.annotate(date_end=F('date_start') + Interval(F('duration'), 'hour')).
filter(date_end__lte=datetime.datetime.now(pytz.utc)))
  • 经测试:Django == 1.8.15,Postgres:9.4.5

  • 此实现仅适用于Postgres,对于另一个DB,您应该覆盖相关方法:'as_postgresql','as_oracle'

答案 1 :(得分:0)

由于事实filter_date不是模型的字段,因此您建议的查询会出错。

从我的观点来看,您尝试做的事情是获取some_date大于hours之前的对象。这是实现这一目标的查询:

some_model.objects.filter(
    some_date__gte=datetime.datetime.now()-datetime.timedelta(hours=hours))

答案 2 :(得分:0)

您可以使用custom QuerySet执行此操作。我建议创建自定义过滤器方法,而不是覆盖现有过滤器方法。

更新基于https://stackoverflow.com/a/33916628/3627387 您可以使用extra

来实现它
class CustomQuerySet(models.QuerySet):
    def date_filter(self):
        # using
        return self.extra(where=["some_date + hours * INTERVAL '1 hour' >= %s"], params=[datetime.now()])

class some_model(models.Model):
    some_date = models.DateTimeField()
    hours = models.IntegerField()

    objects = CustomQuerySet.as_manager()

# And then in your code
some_model.objects.date_filter()