values_list django如何工作?
我有value_list
有趣的经验,我不知道为什么它以这种方式行事。values_list django如何工作?
我想更新TestObject
中的任何值,其中value_1
为value_2
,任何value_2值为value_1。其中value_1
和value_2
来自Value并且TestObject
具有Value的外键。
这是我的代码:
def _swap(value_1, value_2):
from_values_ids = TestObject.objects.filter(value=value_1).values_list('id', flat=True)
to_values_ids = TestObject.objects.filter(value=value_2).values_list('id', flat=True)
TestObject.objects.filter(id__in=from_values_ids).update(value=value_2)
TestObject.objects.filter(id__in=to_values_ids).update(value=value_1)
我的TestObject试验时,有value_1
,但没有任何value_2
。 运行此功能后,最终结果没有任何发生。经过调查,我发现的TestObject得到运行后更新为value_2
:
TestObject.objects.filter(id__in=from_values_ids).update(value=value_2)
但它运行
TestObject.objects.filter(id__in=to_values_ids).update(value=value_1)
我想之后返回可能to_values_ids
具有延迟加载,这就是为什么我添加print to_values_id
。
def _swap(value_1, value_2):
from_values_ids = TestObject.objects.filter(value=value_1).values_list('id', flat=True)
to_values_ids = TestObject.objects.filter(value=value_2).values_list('id', flat=True)
print to_values_ids
TestObject.objects.filter(id__in=from_values_ids).update(value=value_2)
TestObject.objects.filter(id__in=to_values_ids).update(value=value_1)
但是我得到了同样的结果。虽然我的打印to_values_ids
有[]
。
我解决这个问题,我创建一个新的列表与IDS和它的工作,但仍然需要了解核心Python中是如何工作的呢?任何好的解释。
您遇到的问题可能是由于一个事实,即Django的查询集values_lists回报发电机。由于1.9,QuerySet.values_list
实现像FlatValuesListIterable此前1.9迭代类,QuerySet.values_list
返回一个实例的ValuesListQuerySet ......这两个返回一个发电机,所以查询每次访问变量时执行(因此你的行为打电话时看到了打印)。
产生的对象的行为很像一个列表,这是混乱的,但如果你需要证明它不是一个列表,试试这个:
from_values_ids = TestObject.objects.filter(value=value_1).values_list('id', flat=True)
from_list_ids = [obj.id for obj in TestObject.objects.filter(value=value_1)]
combined_list = from_values_ids + from_list_ids
...这将导致:
TypeError: unsupported operand type(s) for +: 'ValuesListQuerySet' and 'list'
的解决方案是简单地投你from_values_ids
变量列表:
from_values_ids = list(TestObject.objects.filter(value=value_1).values_list('id', flat=True))
或只是自己生成列表:
from_values_ids = [obj.id for obj in TestObject.objects.filter(value=value_1)]
你的理解是正确的。 Django querysets are lazy。
from_values_ids = TestObject.objects.filter(value=value_1).values_list('id', flat=True) # doesn't hit the db
to_values_ids = TestObject.objects.filter(value=value_2).values_list('id', flat=True) # doesn't hit the db
现在,当你这样做:
TestObject.objects.filter(id__in=from_values_ids).update(value=value_2)
|
|__> will fetch from db
现在所有匹配value_1
价值得到了更新,以value_2
。现在,下一行执行:
TestObject.objects.filter(id__in=to_values_ids).update(value=value_1)
|
|__> Will actually execute the query you assigned it
# TestObject.objects.filter(value=value_2).values_list('id', flat=True)
此时匹配value_2
是获取和更新,以value_1
的所有对象,但你看到的没有什么区别,因为你开始之前,必须在数据库中的所有value_1
。因此from_values_ids
获取所有对象并将其更新为value_2
,然后回到value_1
。请参阅在数据库中混合使用value_1
和value_2
记录。差异将是显而易见的。
尝试打印两者。如果你的'to_values_ids = []'这意味着你没有更新任何东西! –
两次更新之前的列表to_values_ids是空的,但在运行TestObject.objects.filter(id__in = from_values_ids).update(value = value_2)后,它已更改。为什么会发生? – amm
'QuerySets'作为值返回,而不是引用,所以不应该发生...... –