2

TLDR使用django 的 queryset api 方法的where参数时,extra您可以插入自定义 SQL,该 SQL 将被AND编辑到您的查询中。我有一种情况,我需要这些值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 子句被编入查询OR

4

1 回答 1

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()
于 2012-11-23T20:09:43.513 回答