Django:了解 .values() 和 .values_list() 用例
Django: understanding .values() and .values_list() use cases
我无法理解在什么情况下 .values() 或 .values_list() 比仅使用模型实例更好?
我认为以下都是等价的:
results = SomeModel.objects.all()
for result in results:
print(result.some_field)
results = SomeModel.objects.all().values()
for result in results:
print(result['some_field'])
results = SomeModel.objects.all().values_list()
for some_field, another_field in results:
print(some_field)
显然这些都是愚蠢的例子,谁能指出使用 .values() / .values_list() 而不是直接使用 Model 实例的充分理由?
编辑:
我做了一些简单的分析,使用包含 2 个 CharField(max_length=100) 的 noddy 模型
迭代仅 500 个实例以将 'first' 复制到另一个变量,取 200 次运行的平均值我得到以下结果:
Test.objects.all() time: 0.010061947107315063
Test.objects.all().values('first') time: 0.00578328013420105
Test.objects.all().values_list('first') time: 0.005257354974746704
Test.objects.all().values_list('first', flat=True) time: 0.0052023959159851075
Test.objects.all().only('first') time: 0.011166254281997681
所以答案很明确:性能! (大多数情况下,请参阅下面的 knbk 答案)
values() 和 values_list() 都旨在作为特定用例的优化:检索数据子集而无需创建模型实例的开销。 Django Documentation.
中给出了很好的解释
.values()
和 .values_list()
转换为 GROUP BY
查询。这意味着具有重复值的行将被分组为一个值。假设你有一个模型 People
以下数据:
+----+---------+-----+
| id | name | age |
+----+---------+-----+
| 1 | Alice | 23 |
| 2 | Bob | 42 |
| 3 | Bob | 23 |
| 4 | Charlie | 30 |
+----+---------+-----+
然后 People.objects.values_list('name', flat=True)
将 return 3 行:['Alice', 'Bob', 'Charlie']
。名称为 'Bob'
的行被分组为一个值。 People.objects.all()
将 return 4 行。
这在做注释时特别有用。你可以这样做People.objects.values_list('name', Sum('age'))
,它会return以下结果:
+---------+---------+
| name | age_sum |
+---------+---------+
| Alice | 23 |
| Bob | 65 |
| Charlie | 30 |
+---------+---------+
如您所见,Bob 的年龄已相加,并且 return 排在一行中。这与 distinct()
不同,它仅在注释之后应用。
性能只是一个副作用,尽管它非常有用。
我无法理解在什么情况下 .values() 或 .values_list() 比仅使用模型实例更好?
我认为以下都是等价的:
results = SomeModel.objects.all()
for result in results:
print(result.some_field)
results = SomeModel.objects.all().values()
for result in results:
print(result['some_field'])
results = SomeModel.objects.all().values_list()
for some_field, another_field in results:
print(some_field)
显然这些都是愚蠢的例子,谁能指出使用 .values() / .values_list() 而不是直接使用 Model 实例的充分理由?
编辑:
我做了一些简单的分析,使用包含 2 个 CharField(max_length=100) 的 noddy 模型 迭代仅 500 个实例以将 'first' 复制到另一个变量,取 200 次运行的平均值我得到以下结果:
Test.objects.all() time: 0.010061947107315063
Test.objects.all().values('first') time: 0.00578328013420105
Test.objects.all().values_list('first') time: 0.005257354974746704
Test.objects.all().values_list('first', flat=True) time: 0.0052023959159851075
Test.objects.all().only('first') time: 0.011166254281997681
所以答案很明确:性能! (大多数情况下,请参阅下面的 knbk 答案)
values() 和 values_list() 都旨在作为特定用例的优化:检索数据子集而无需创建模型实例的开销。 Django Documentation.
中给出了很好的解释.values()
和 .values_list()
转换为 GROUP BY
查询。这意味着具有重复值的行将被分组为一个值。假设你有一个模型 People
以下数据:
+----+---------+-----+
| id | name | age |
+----+---------+-----+
| 1 | Alice | 23 |
| 2 | Bob | 42 |
| 3 | Bob | 23 |
| 4 | Charlie | 30 |
+----+---------+-----+
然后 People.objects.values_list('name', flat=True)
将 return 3 行:['Alice', 'Bob', 'Charlie']
。名称为 'Bob'
的行被分组为一个值。 People.objects.all()
将 return 4 行。
这在做注释时特别有用。你可以这样做People.objects.values_list('name', Sum('age'))
,它会return以下结果:
+---------+---------+
| name | age_sum |
+---------+---------+
| Alice | 23 |
| Bob | 65 |
| Charlie | 30 |
+---------+---------+
如您所见,Bob 的年龄已相加,并且 return 排在一行中。这与 distinct()
不同,它仅在注释之后应用。
性能只是一个副作用,尽管它非常有用。