您的位置:

为什么ValueError("When merging querysets using 'or', you cannot have ""extra(select=...) on both sides."),怎么解决

  发布时间:2023-04-02 19:02:38
如何解决解决这个问题的方法是确保在使用 'or' 或 '|' 操作符连接查询集时,不要在两个查询集上使用额外的'extra'选项。具体做法可以尝试如下方法:- 只在一个查询集上使用extra()- 使用额外的条件语句来连接两个查询集而不是使用 'or' 或 '|' 运算符- 将extra()应用在最终的查询集上例如这段代码应该改为或者这样就能避免这个错误了。在这种情况下,您需要使用 'distinct()' 方法来确保查询结果中没有重复的对象这样就能避免重复的数据了。

报错的原因

这个错误通常是因为在使用 'or' 或 '|' 运算符将两个具有额外 'extra(select=...)' 选项的查询集合并时出现的。

这是因为在使用 'or' 运算符时,Django 无法正确地将两个具有额外选项的查询集合并,因为它不知道如何处理多个额外选项。

解决方法是:

-将额外选项应用于单个查询集,而不是将它们应用于两个查询集

-使用条件语句来连接两个查询集而不是使用 'or' 或 '|' 运算符

-将查询集的.extra() 应用在最终的查询集的最后

例如:


qs1 = Model.objects.filter(...)
qs2 = Model.objects.filter(...).extra(select={'new_field':'value'})
qs = qs1 | qs2.extra(select={'new_field':'value'})

这段代码应该改为:


qs1 = Model.objects.filter(...)
qs2 = Model.objects.filter(...)
qs = qs1 | qs2
qs = qs.extra(select={'new_field':'value'})

或者:


qs1 = Model.objects.filter(...)
qs2 = Model.objects.filter(...).extra(select={'new_field':'value'})
qs = qs1.filter(Q(...) | Q(id__in=qs2))

这样就能避免这个错误了。

如何解决

解决这个问题的方法是确保在使用 'or' 或 '|' 操作符连接查询集时,不要在两个查询集上使用额外的'extra(select=...)'选项。

具体做法可以尝试如下方法:

- 只在一个查询集上使用extra()

- 使用额外的条件语句来连接两个查询集而不是使用 'or' 或 '|' 运算符

- 将extra()应用在最终的查询集上

例如


qs1 = Model.objects.filter(...)
qs2 = Model.objects.filter(...).extra(select={'new_field':'value'})
qs = qs1 | qs2.extra(select={'new_field':'value'})

这段代码应该改为:


qs1 = Model.objects.filter(...)
qs2 = Model.objects.filter(...)
qs = qs1 | qs2
qs = qs.extra(select={'new_field':'value'})

或者


qs1 = Model.objects.filter(...)
qs2 = Model.objects.filter(...).extra(select={'new_field':'value'})
qs = qs1.filter(Q(...) | Q(id__in=qs2))

这样就能避免这个错误了。

使用例子

是的,下面是一个例子,演示如何在两个带有额外选项的查询集之间使用条件语句连接而不是使用 'or' 运算符:


# First queryset with an extra option
qs1 = MyModel.objects.filter(published=True)

# Second queryset with an extra option
qs2 = MyModel.objects.filter(author__username='john').extra(select={'new_field':'value'})

# Merging the querysets using 'Q' object
qs = MyModel.objects.filter(Q(pk__in=qs1) | Q(pk__in=qs2))

这样的话我们使用的是条件语句来连接两个查询集而不是 'or' 运算符,就能避免上面提到的错误了。

或者,您可以将额外的选项添加到最终查询集中


# First queryset
qs1 = MyModel.objects.filter(published=True)

# Second queryset
qs2 = MyModel.objects.filter(author__username='john')

# Merging the querysets using 'or'
qs = qs1 | qs2
qs = qs.extra(select={'new_field':'value'})

这样的话额外的选项就被添加到最终查询集中,也不会出现上述错误了

另外需要注意的是,如果您的查询集本身就是从其他查询集中进行过滤和筛选的,那么您可能会在合并这些查询集时遇到这个错误。在这种情况下,您需要使用 'distinct()' 方法来确保查询结果中没有重复的对象。


qs1 = MyModel.objects.filter(published=True)
qs2 = MyModel.objects.filter(author__username='john')
qs = qs1.filter(Q(...) | Q(id__in=qs2)).distinct()

这样就能避免重复的数据了。如果还有疑问可以继续提问。