Python Django 1.9:为QuerySet创建复杂的自定义筛选器方法
我们的目标是创建一个Python Django 1.9:为QuerySet创建复杂的自定义筛选器方法,python,sql,django,filter,django-queryset,Python,Sql,Django,Filter,Django Queryset,我们的目标是创建一个定制的_filter方法,该方法可以链接到标准的Django filter方法。custom_filter方法可能需要一些原始SQL代码。在最好的情况下,QuerySet的计算结果仍然是惰性的 最终,这样的命令将是伟大的: apple_query_set = Apple.objects.filter(<any standard filtering>).custom_filter() 自定义过滤器的目标是按(a,b)对Apple实例进行分组,并针对每个实例进行分组
定制的_filter
方法,该方法可以链接到标准的Django filter方法。custom_filter
方法可能需要一些原始SQL代码。在最好的情况下,QuerySet的计算结果仍然是惰性的
最终,这样的命令将是伟大的:
apple_query_set = Apple.objects.filter(<any standard filtering>).custom_filter()
自定义过滤器的目标是按(a,b)
对Apple实例进行分组,并针对每个实例进行分组
组仅根据日期返回最新实例
此类筛选器的原始SQL代码如下所示:
custom_filter_raw_sql = """
SELECT t1.id
FROM app_apple AS t1
INNER JOIN (SELECT a, b, max(date) AS max_date
FROM app_apple
GROUP BY a, b) AS t2
ON t1.a = t2.a AND t1.b = t2.b AND t1.date = t2.max_date;
"""
到目前为止,为了添加自定义过滤器
功能,
我已尝试(未成功)将objects=AppleQuerySet.as\u manager()
添加到Apple类,包括:
class AppleQuerySet(models.QuerySet):
def custom_filter(self):
subquery = """
SELECT t1.id
FROM app_apple AS t1
INNER JOIN (SELECT a, b, max(date) AS max_date
FROM app_apple
GROUP BY a, b) AS t2
"""
condition = "t1.a = t2.a AND t1.b = t2.b AND t1.date = t2.max_date"
return self.extra(tables=[subquery], where=[condition])
但是,我不确定这种方法是否有可能像自定义查询那样起作用
不仅应适用于所有Apple实例(Apple.objects.
),还应能够将其链接到已筛选的查询集(Apple.objects.filter()
)
创建此自定义可链接(惰性)自定义过滤器
功能的最佳方法是什么?我哪里做错了?非常感谢 我想你需要的是一个定制经理。请在
这里您可以看到一个使用原始SQL代码的示例:
from django.db import models
class PollManager(models.Manager):
def with_counts(self):
from django.db import connection
cursor = connection.cursor()
cursor.execute("""
SELECT p.id, p.question, p.poll_date, COUNT(*)
FROM polls_opinionpoll p, polls_response r
WHERE p.id = r.poll_id
GROUP BY p.id, p.question, p.poll_date
ORDER BY p.poll_date DESC""")
result_list = []
for row in cursor.fetchall():
p = self.model(id=row[0], question=row[1], poll_date=row[2])
p.num_responses = row[3]
result_list.append(p)
return result_list
这是另一种方法,但我想知道您是否只能使用和的组合来实现预期的结果:
Apple.objects.order_by('a', 'b', '-date').distinct('a', 'b')
如果在order\u by
和distinct
中保持字段的顺序相同,则此组合有效
这样,如果需要,您还可以提前使用链接的过滤器
一些解释:
使用以下命令只会将具有类似a
和b
的所有对象放在一起
Apple.objects.order_by('a', 'b')
但是,您可以按-date
(降序)对组中的对象(具有相同的a
和b
值)进一步排序
现在,所有具有类似a
和b
的对象都在一起,并且在每个组中,第一个元素具有最新的日期。因此,我们可以使用distinct('a','b')
有没有具体的原因让你不能直接使用查询本身的所有过滤条件?@AKS这可能是一个解决方案,但我不知道如何确保SQL代码可以任意链接到查询集(而不是对整个Apple表进行过滤)。我很高兴看到一些代码如何做到这一点。(另外,我不确定这个解决方案是否允许延迟计算。)如果返回的值应该是QuerySet,这个解决方案会是什么样子?该方法是否可以作为链式过滤器应用(而不是在整个Apple表上重新运行查询?)。此解决方案是否允许延迟评估?这里展示了如何从自定义管理器创建自定义查询集,它应该回答前两个问题。我不知道你说的“允许惰性评估”是什么意思这是一个优雅的答案@AKS,您认为(在本例中当然)通过自定义SQL添加过滤器链步骤的笨拙方法在技术上是可行的吗?在这种情况下,是否有示例代码?谢谢@elke,您坚持使用您提到的方法有什么特别的原因吗?我之所以这样说,是因为使用上述现有的django功能可以很容易地实现您想要的结果。@AKS,对于上面的示例,您的方法绝对是首选。我的想法是,如果另一个用户偶然发现本文,“如何将类似复杂的sql查询插入queryset筛选器”的答案可能是她要搜索的,而不是我的特定示例问题的解决方案。然而,也许所有的问题最终都有如此优雅的解决方案?
Apple.objects.order_by('a', 'b')
Apple.objects.order_by('a', 'b', '-date')
Apple.objects.order_by('a', 'b', '-date').distinct('a', 'b')