【问题标题】:Django filter query on with property fields automatically calculatedDjango过滤查询,自动计算属性字段
【发布时间】:2015-07-27 16:47:47
【问题描述】:

有自动计算属性字段的 Django Order 模型。如何进行过滤查询。

class Order(models.Model):

    @property
    def expire(self):
        return self.created + datetime.timedelta(days=self.days_left())

    @property
    def days_left(self):
        return self.recurrence_period  * self._recurrence_unit_days[self.recurrence_unit]

从今天开始计算得到 1,3,7 日期时间天

settings.SUBSCRIPTION_EXPIRATION_REMIND = [1, 3, 7]

days = map(lambda x: datetime.date.today() + datetime.timedelta(days=x), settings.SUBSCRIPTION_EXPIRATION_REMIND)

[datetime.date(2015, 7, 28),
 datetime.date(2015, 7, 30),
 datetime.date(2015, 8, 3)]

如何通过ORM查询过滤

Order.objects.filter(expire__in=days)

Django 抛出错误。

FieldError: Cannot resolve keyword 'expire' into field.

【问题讨论】:

  • 我想,我知道这是不可能的,但是如何绕过它

标签: python django django-models


【解决方案1】:

不,您不能根据模型方法或属性执行查找。 Django ORM 不允许这样做。

查询被编译为 SQL 以在数据库级别发送和处理,而属性是 Python 代码,数据库对它们一无所知。这就是为什么 Django 过滤器只允许我们使用数据库字段的原因。

可以这样做:

Order.objects.filter(created=..) # valid as 'created' is a model field

不能这样做:

Order.objects.filter(expires=..) # INVALID as 'expires' is a model property

您可以改为使用列表推导来获得所需的结果。

[obj for obj in Order.objects.all() if obj.expire in days]

上面将为我提供days 列表中具有expire 值的Order 对象列表。

【讨论】:

  • 实现它时不断出错。 KeyError:没有,即使它们是记录
  • 应该可以了,请重新检查数据库中是否有记录。尝试放置一个调试器,看看是否缺少任何东西以及你在哪里得到KeyError
  • 我确实根据您的建议使用了该列表。但它没有正确执行过滤stackoverflow.com/questions/37649078/…
  • 重要的是要注意,通过使用列表推导,您正在强制评估,现在您的数据类型是list,而不是QuerySet。这在很多情况下都不起作用,例如 get_queryset() 方法。
  • 我会详细说明@TaylorEdmiston 评论,迭代QuerySet 对象(此处为Order.objects.all())将强制数据库遍历Order 表中的所有现有记录。由于性能原因,这是完全不能接受的。如果您想通过模型的方法或属性查询数据库,则可以考虑将它们相应地设为具有数据库索引的模型字段
【解决方案2】:

我不认为你可以在字段查找中使用属性,因为文档说 The field specified in a lookup has to be the name of a model field https://docs.djangoproject.com/en/1.8/topics/db/queries/#field-lookups

【讨论】:

    【解决方案3】:

    最终为模型添加过期时间,计算保存方法的值。现在我可以了

     Order.objects.filter(expire__in=days)
    

    【讨论】:

    • 这不是解决方案。
    • 'expire' 不是 db 层模型的实际字段!所以django无法解决。绝对不行。
    • expire是可以计算出来的,这个不是解决办法,可以获取创建日期,做范围查询
    • 您无法根据模型方法或属性执行查找。
    猜你喜欢
    • 2021-09-27
    • 2016-11-07
    • 1970-01-01
    • 2020-08-14
    • 2022-11-14
    • 1970-01-01
    • 2018-08-08
    • 2017-12-12
    • 2013-06-11
    相关资源
    最近更新 更多