目标是创建一个可以链接到标准Django过滤器方法的custom_filter
方法。 custom_filter
方法可能需要一些原始SQL代码。在最好的情况下, QuerySet 仍然会被评估为懒惰。
最后,这样的命令会很棒:
apple_query_set = Apple.objects.filter(<any standard filtering>).custom_filter()
这是模型:
class Apple(models.model):
a = models.IntegerField()
b = models.IntegerField()
date = models.DateField()
custom_filter
的目标是按(a,b)
对每个Apple实例进行分组
group仅根据date
返回最新实例。
此类过滤器的原始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;
"""
到目前为止,为了添加custom_filter
功能,
我已尝试(未成功)将objects = AppleQuerySet.as_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()
)
创建此自定义可链接(懒惰)custom_filter
功能的最佳方法是什么?我哪里错了?非常感谢!
答案 0 :(得分:1)
这是一种替代方式,但我想知道您是否只能使用order_by
和distinct
的组合来达到预期效果:
auto x = Proxy().method1().method2(); // no
Proxy p; // no
Target x = Proxy(); //yes
Target x = Proxy().method1().method2(); //yes
如果您在Apple.objects.order_by('a', 'b', '-date').distinct('a', 'b')
和order_by
中保持字段顺序相同,则此组合有效。
并且,通过这种方式,如果需要,您还可以事先使用链式distinct
。
一些解释:
使用以下内容只会将所有具有相似filter
和a
的对象放在一起
b
但是,您可以按Apple.objects.order_by('a', 'b')
(按递减顺序)对组中的对象(具有相同的a
和b
值)进行排序
-date
现在,所有具有相似Apple.objects.order_by('a', 'b', '-date')
和a
的对象都在一起,并且在每个组中,第一个元素具有最新的b
。因此,我们可以使用date
distinct('a', 'b')
答案 1 :(得分:-1)
我认为您需要的是自定义经理。在Django documentation
上查看在这里,您可以看到一个使用原始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