TLDR 使用where
parameter of the extra
method of django's queryset api时,您可以插入对您的查询AND
的自定义SQL。我有一种情况,我需要重置OR
来重置查询。这有支持吗?
我有一个大表与另一个表有M2M关系
class BookName:
name = models.CharField(db_index=True)
other_names = models.ManyToManyField(OtherName)
class OtherBookName:
name = models.CharField(db_index=True)
我想查询列表中具有全名或替代名称的图书。
使用Q()
会自然减慢速度。
我的解决方案是首先查询OtherBookName
以查找列表中包含名称的行并返回这些pks(索引时速度很快)。然后我手动在两个模型之间包含M2M表,并添加一个where
子句,该子句还应该拉出表中匹配的BookName
实例。
test_names = ["Foo", "Bar",]
other_ids = OtherBookName.objects.filter(name__in=test_names).values_list("id", flat=True)
queryset = self\
.filter(Q(name__in=test_names)) \
.extra(
where=[
"bookname_id = app_bookname.id",
"booknameotherbookname_id IN (%s)"
% ",".join([str(id) for id in other_ids]),
],
tables=["app_bookname_otherbookname",]) \
.distinct()
这非常接近于工作,除了我想要AND
时我的where claus是OR
。
答案 0 :(得分:0)
试试这个:
names = ["Foo", "Bar",]
other_ids = OtherBookName.objects.filter(name__in=names).values_list("id", flat=True)
where_clause = "bookname_id = app_bookname.id AND (name IN (%s)" \
% ",".join(names) + " OR booknameotherbookname_id IN (%s))" \
% ",".join([str(id) for id in other_ids])
queryset = self\
.extra(
where=[where_clause],
tables=["app_booknames_otherbookname",]) \
.distinct()