如何获取所有行的查询集,每个查询集只包含特定的字段?

160

我有一个名为Employees的模型,我想要一个QuerySet包含所有行,但只包含每行的一些特定字段而不是全部字段。

我知道如何查询表/模型中的所有行:

Employees.objects.all()

我想知道如何为每个Queryset元素选择字段。我该怎么做?


1
“仅使用一个”是什么意思?是指使用 SELECT col 而不是 SELECT * 吗? - Ciro Santilli OurBigBook.com
9个回答

274
Employees.objects.values_list('eng_name', flat=True)

这将创建一个所有 eng_name 的平坦列表。如果您想每行有多个字段,不能使用平坦列表:这将创建元组列表:

Employees.objects.values_list('eng_name', 'rank')

谢谢您的答复,如果我只想选择一个或多个字段(而不是全部),该怎么办? - zentenk
抱歉,我不理解这个问题。 - Daniel Roseman
4
请分享这个文件,这将有助于其他人。 - bob marti
values_list 返回类似值的字典还是对象? - Darwin
'QuerySet' 对象没有属性 'objects'。 - Matthaeus Gaius Caesar

48

除了 values_list,正如Daniel提到的那样,您还可以使用only(或相反效果的defer)来获取仅具有其id和指定字段的对象的查询集:

Employees.objects.only('eng_name')

这将运行单个查询:

SELECT id, eng_name FROM employees

7
这个命令返回我在 Django 版本 2.1.3 和 Python 版本 3.6.2 中的所有字段。 - Ananthi
3
它只会获取一个字段,但如果您尝试访问其他字段,则会执行单独的数据库查询。因此,这是一种良好的优化技术,但请确保不要创建这些额外的查询。否则,您将失去性能而不是获得它。 - Eerik Sven Puudist
only 和 values 的区别在于 only 还会获取 id。 - Darwin

21
我们可以选择需要的字段进行筛选。
Employee.objects.all().values('eng_name','rank')

查询成功运行后,如何将字段的值存储在变量中,例如 **var_name = <query_name>.<field_name>**? - Love Putin Not War
@user12379095 就像这样简单:var_name = Employee.objects.all().values('eng_name','rank') - theQuestionMan
@user12379095 然后使用这个变量名 - 例如:打印所有员工的姓名和职级,你可以这样做:for person in var_name: print(person['eng_name'] + " " + person['rank']) - theQuestionMan

8

Daniel的答案非常准确。如果你想查询多个字段,请这样做:

Employee.objects.values_list('eng_name','rank')

这将返回一个元组列表。当查询多个字段时,您不能使用named=True。

此外,如果您知道只有一个带有该信息的字段,并且您知道pk id,则可以执行以下操作:

Employee.objects.values_list('eng_name','rank').get(pk=1)

3

Oskar Persson的答案是最佳的处理方式,因为它使得将数据传递到上下文并从模板中正常处理数据变得更加容易,因为我们可以获得对象实例(可以轻松迭代以获取属性),而不是一个简单的值列表。

之后,您可以轻松地获取所需的属性:

for employee in employees:
    print(employee.eng_name)

或者在模板中:

{% for employee in employees %}

    <p>{{ employee.eng_name }}</p>

{% endfor %}

2
您可以像这样在筛选器旁使用values_list;
active_emps_first_name = Employees.objects.filter(active=True).values_list('first_name',flat=True)

更多细节在这里


2
Employees.objects.filter().only('eng_name')

这将提供一个查询集,其中包含所有行,但仅具有指定的字段。它不像上面的其他答案一样给出列表。它会给你对象实例。请注意; 它是objects.filter().only()而不是just objects.only()
它类似于SQL查询:
SELECT eng_name FROM Employees;

1
queryset = ModelName.objects.filter().only('field1', 'field2')

0
您还可以使用带有字段名称的列表。
field_names = ['product_id', 'name', 'price', 'status']
results = ModelName.objects.all().values_list(*field_names)

# or for example
# results = ModelName.objects.all().values_list(*field_names, named=True)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接