我有以下型号:
class Work(models.Model):
visible = models.BooleanField(default=False)
class Book(models.Model):
work = models.ForeignKey('Work')
我试图像这样更新一些行:
qs=Work.objects.all()
qs.annotate(Count('book')).filter(Q(book__count__gt=1)).update(visible=False)
然而,这是一个错误:
DatabaseError:子查询包含太多列 第1行:... SET“可见”= false WHERE“app_work”。“id”IN(SELECT ...
如果删除update子句,查询运行没有问题,并返回我期望的内容。
对于带有注释后跟更新的查询,似乎会发生此错误。有没有其他方式来写这个?
答案 0 :(得分:10)
如果没有让玩具数据库能够复制您的问题并尝试解决方案,我至少可以建议Django: Getting complement of queryset中的方法作为一种可能的方法。
尝试这种方法:
qs.annotate(Count('book')).filter(Q(book__count__gt=1))
Work.objects.filter(pk__in=qs.values_list('pk', flat=True)).update(visible=False)
答案 1 :(得分:5)
您还可以非常简单地清除查询集中的注释:
qs.query.annotations.clear()
qs.update(..)
这意味着您只会触发一个查询,而不是一个查询,但如果您的查询依赖于要过滤的注释,请不要使用此项。这很棒用于删除数据库生成的连接,以及偶尔添加到模型的默认查询中的实用程序垃圾...但问题中的示例是一个完美的示例,说明这不起作用。
答案 2 :(得分:1)
我已经重复了这个问题&相信它是Django ORM的一个bug。 @acjay答案是一个很好的解决方法。错误报告:https://code.djangoproject.com/ticket/25171
在Django 2 alpha中发布的修补程序:https://code.djangoproject.com/ticket/19513
答案 3 :(得分:1)
要添加到Oli的答案:如果需要更新注释,请先执行过滤,然后将结果存储在变量中,然后调用该查询集中没有参数的过滤器来访问{{1}像这样的函数:
update