个性化定制 Django 过滤器模型字段

4

我有一个以下的模型

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个回答

3

另一种优雅的方法是创建数据库函数。

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

from django.db import models

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

数据库功能实现:

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对象。作为第二个参数,它可以是:'second','minute','hour','day'。

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,PostgreSQL:9.4.5

  • 此实现仅适用于PostgreSQL,对于其他数据库,您应该覆盖相关方法:“as_postgresql”,“as_oracle”


0

你提出的查询将会出现错误,因为filter_date不是该模型的一个字段。

从我的角度来看,你想要做的是获取一些日期比hours小时之前更大的对象。这是实现此目的的查询:

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

是的,我知道,但我想自定义那个模型字段。 - NIKHIL RANE
filter 方法基本上形成了一个要在数据库上执行的 SQL 查询。因此,答案是您不能在数据库表中不存在的字段上使用查找。 - Dmitry Yantsen

0

你可以使用自定义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()

我想在模型字段中添加timedelta(some_date+timedelta(hours)),然后在some_date上使用gte过滤器(some_date+timedelta(hours) gte temp_date),类似这样的操作。 - NIKHIL RANE
有什么区别吗?从数学上讲,some_date+timedelta(hours)_gte=temp_datesome_date_gte=temp_date-timedelta(hours)是相同的。但第一个在Django ORM中是不可能的。所以我和@table建议您用这种方式来实现。 - Sardorbek Imomaliev
hours是我的模型字段,那么我该如何将这个hours传递给日期过滤器呢? - NIKHIL RANE
@NIKHILRANE 请查看更新的答案。在Django中目前无法实现此功能。但是您可以使用extra并使用原始SQL来实现。 - Sardorbek Imomaliev

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接