Python 使用exists()和value_list()的Django queryset缓存

Python 使用exists()和value_list()的Django queryset缓存,python,django,python-3.x,python-2.7,django-models,Python,Django,Python 3.x,Python 2.7,Django Models,比方说,我正在尝试将所有名为John的配置文件的名称更改为Mike queryset = Profile.objects.filter(name='John') 方法1: if queryset: queryset.update(name='Mike') logger.info(f'Updated the following profiles: {queryset.values_list('id', flat=True)}') 方法2: if queryset.exists(

比方说,我正在尝试将所有名为
John
的配置文件的名称更改为
Mike

queryset = Profile.objects.filter(name='John')
方法1:

if queryset:
    queryset.update(name='Mike')
    logger.info(f'Updated the following profiles: {queryset.values_list('id', flat=True)}')
方法2:

if queryset.exists():
    queryset.update(name='Mike')
    logger.info(f'Updated the following profiles: {queryset.values_list('id', flat=True)}')
问题:更新名为
John
的所有字段并记录更新的记录ID的最有效方法是什么?

在方法1中,如果queryset评估整个queryset,则调用

在方法2中,使用
queryset.exists()
queryset.update(…)
调用进行查询

最有效的方法是完全跳过条件
if
语句,只需调用
queryset.update(…)
。调用的返回值将包括更新的行数,可能是
0

为了测试差异,我们可以使用
django.db.connection
,它将列出所有执行的查询,以及它们花费的时间

从django.db导入连接,重置\u查询
从django.contrib.models导入用户
def方法_1(查询集):
如果查询集:
查询集更新(first_name=“Mike”)
def方法_2(查询集):
如果queryset.exists():
查询集更新(first_name=“Mike”)
def方法_3(查询集):
查询集更新(first_name=“Mike”)
>>>connection.querys==[]#开始时为空
真的
>>>方法_1(User.objects.all())
>>>[查询[“时间”]用于连接中的查询。查询]
['0.051', '0.126']
>>>重置查询()
>>>方法2(User.objects.all())
>>>[查询[“时间”]用于连接中的查询。查询]
['0.001', '0.125']
>>>重置查询()
>>>方法3(User.objects.all())
>>>[查询[“时间”]用于连接中的查询。查询]
['0.122']

如您所见,
方法\u 3
仅使用一个查询来执行更新,并且比其他方法更快。

如果必须获取每个更新配置文件的ID,则应首先查询,因为在更新行后,将无法再次查询此信息。您可以使用此操作的结果来确定是否应运行更新

profile_ids_to_update = list(queryset.values_list('id', flat=True))
if profile_ids_to_update:
    queryset.update(name='Mike')
    logger.info(f'Updated the following profiles: {profile_ids_to_update}')

这将导致最多2个查询,如果没有要更新的行,则只会有1个

相反:方法2更有效。方法1获取整个查询集,方法2不获取。最有效的方法是不使用
.exists()
,也不测试查询集的真实性。只要调用更新,如果没有行与queryset匹配,那么它基本上与测试现有行相同anyway@IainShelvington你提出了一个有趣的观点,我提前道歉,但是如果我想记录所有更新的配置文件ID呢?我的意思是,我仍然需要对queryset求值,因此我认为现在的方法1会更有效。@在您的示例中,对
queryset.values\u list
的调用会再次调用DB,但不会有名称等于“John”的行,因为所有这些行都是updated@IainShelvington有意思,,因此,运行value\u list将再次查询,而不给我任何值。那么,在更新的同时还要记录所有修改的ID的最有效方法是什么?