我们都知道 Django 提供了开箱即用的强大的 ORM,用ORMk可以让我们不懂SQL也可以很方便的去完成对数据库的修改操作,例如查询,删除等。在日常工作中,我们大多数人只会处理来自 ORM 的 filter()、get()、all()、update() 和 delete() 方法。
但除此之外,Django ORM 还提供了许多其他功能强大的方法,今天我们就来介绍下这些方法的实际使用:
  • exclude()
  • values()
  • values_list()
  • select_related()
  • order_by()
  • exists()
  • count()
  • first() and last()
  • in_bulk()
  • explain()
我将使用以下学生表为上述方法提供示例。这个 Student 类来自 models.py 文件:
classStudent(models.Model):
    name = models.CharField(max_length=
100
)

    grade = models.IntegerField()

    section = models.CharField(max_length=
10
)

    school = models.ForeignKey(School, on_delete=models.CASCADE)

    blood_group = models.CharField(max_length=
10
)

    mobile = models.CharField(max_length=
20
)

    address = models.TextField()

def__str__(self):
return
 self.name

学生表与学校表有外键关系。
classSchool(models.Model):
    name = models.CharField(max_length=
100
)

    email = models.EmailField(null=
True
, blank=
True
)

    address = models.TextField()

def__str__(self):
return
 self.name

让我们正式开始。
1、exclude()
第一种方法是 exclude() 方法。这个方法基本上会返回一个查询集,不包括我们给出的值。我的学生桌上有 4 个学生。首先,让我使用 all() 方法获取它们。
>>> 
queryset = Student.objects.all()

>>> 
queryset

<QuerySet [<Student: Regina Johnson>, <Student: Eva Smith>, <Student: Jessie Smith>, <Student: John David>]>

我不希望“Eva Smith”出现在查询集中。所以我可以做这样的事情。我可以在 Student 模型上用她的名字调用 exclude() 方法。
>>> queryset = Student.objects.exclude(name=
'Eva Smith'
)

>>> queryset

<QuerySet [<Student: Regina Johnson>, <Student: Jessie Smith>, <Student: John David>]>

从查询的结果可以看到,已从查询集中排除
2、values()
下一个方法是 values() 方法。此方法返回 Python 字典,而不是 QuerySet 对象。
>>> 
Student.objects.values()<QuerySet [{
'id'
1
'name'
'Regina Johnson'
'grade'
10
'section'
'A'
'school_id'
1
'blood_group'
'A+'
'mobile'
'9791684645'
'address'
'93 Jessica Ln, Depew, NY, 14043'
}, {
'id'
3
'name'
'Eva Smith'
'grade'
12
'section'
'A'
'school_id'
1
'blood_group'
'A1+'
'mobile'
'8907896543'
'address'
'2012 Walnut Ave #J, Ceres, CA, 95307'
}, {
'id'
4
'name'
'Jessie Smith'
'grade'
12
'section'
'A'
'school_id'
1
'blood_group'
'A1+'
'mobile'
'8907896543'
'address'
'503 Courtney Dr, Brusly, LA, 70719'
}, {
'id'
5
'name'
'John David'
'grade'
12
'section'
'A'
'school_id'
1
'blood_group'
'A1+'
'mobile'
'2675431231'
'address'
'34 Leaman Pl, Lynbrook, NY, 11563'
}]>

我们还可以通过提供字段名称作为 values() 方法的参数来仅检索我们需要的字段。假设我只需要学生的“id”和“name”。我可以做这样的事情。
>>> 
Student.objects.values(
'id'
'name'
)<QuerySet [{
'id'
1
'name'
'Regina Johnson'
}, {
'id'
3
'name'
'Eva Smith'
}, {
'id'
4
'name'
'Jessie Smith'
}, {
'id'
5
'name'
'John David'
}]>

3、values_list()
values_list() 方法类似于 values() 方法,但它返回元组而不是返回字典。
>>> 
Student.objects.values_list(
'id'
'name'
)<QuerySet [(
1
'Regina Johnson'
), (
3
'Eva Smith'
), (
4
'Jessie Smith'
), (
5
'John David'
)]>

如果我们只需要一个单一的值,比如一个列表而不是一个元组,我们可以将一个额外的参数 flat=True 传递给 values_list 方法。如果我只想将名称作为列表,可以做这样的事情。
>>> 
Student.objects.values_list(
'name'
, flat=
True
)<QuerySet [
'Regina Johnson'
'Eva Smith'
'Jessie Smith'
'John David'
]>

注意:这仅适用于单个字段。如果提供多个字段,则会出现错误。
>>> 
Student.objects.values_list(
'id'
'name'
, flat=
True
)

TypeError: 
'flat'isnot
 valid when values_list 
is
 called 
with
 more than one field.

4、select_related()
这是我非常喜欢的方法之一。正如我所说,我的学生表与学校表有外键关系。所以为了从学生那里检索学校,我可以这样查询。
>>> 
student = Student.objects.get(pk=
1
)

>>> 
student.school

<School: Montfort>

首先,使用学生 ID 查询学生表以获取特定学生。然后再次为了获得学校,我们执行额外的数据库查找。
注意:每个外键关系都需要额外的数据库查找。
对于我们的简单示例,这不是问题,但是在具有许多外键关系的大型数据库中,数据库的负载可能会令人望而却步。
我们可以使用 select_related() 通过在第一次命中数据库时检索所有相关数据来提高数据库性能。
>>> 
student = Student.objects.select_related(
'school'
).get(pk=
1
)

>>> 
student.school 
# school has already been retrieved. Database is not hit again.
<School: Montfort>

在这种情况下,学校数据是在进行第一次查询时从预取数据中检索出来的,而不是再次查询数据库。
5、order_by()
order_by() 方法更改了 QuerySet 的默认顺序。默认情况下,排序基于主键(id)字段。如果我希望我的 QuerySet 根据名称排序,我可以将名称字段提供给 order_by() 方法。如果我希望我的 QuerySet 根据名称升序排序,我可以做这样的事情.
>>> 
Student.objects.order_by(
'name'
)<QuerySet [<Student: Eva Smith>, <Student: Jessie Smith>, <Student: John David>, <Student: Regina Johnson>]>

如果我想按降序排列名称,我可以像这样查询数据库。


>>> 
Student.objects.order_by(
'-name'
)<QuerySet [<Student: Regina Johnson>, <Student: John David>, <Student: Jessie Smith>, <Student: Eva Smith>]>

字段名称的符号将起作用。
6、exists()
如果返回的 QuerySet 包含一个或多个对象,exists() 方法返回 True,如果 QuerySet 为空,则返回 False。
>>> 
Student.objects.filter(name=
'Regina Johnson'
).exists()

True
>>> 
Student.objects.filter(name=
'Regina David'
).exists()

False
我的数据库有一个名为 Regina Johnson 的学生,因此当调用名称为“Regina Johnson”时,exists() 方法返回 True,在其他情况下则返回 False。
7、count()
count() 方法计算 QuerySet 中的条目数。它可用于对数据库表中的所有对象进行计数。
>>> 
Student.objects.count()

4
或者用于统计查询返回的对象数量:
>>> 
Student.objects.filter(name=
'Regina Johnson'
).count()

1
count() 在功能上等同于使用aggregate() 函数,但它具有更清晰的语法,并且在大型数据集上可能更快。
8、first()和last()
first() 方法返回 QuerySet 中的第一个元素。
>>> 
Student.objects.all()

<QuerySet [<Student: Regina Johnson>, <Student: Eva Smith>, <Student: Jessie Smith>, <Student: John David>]>>>> Student.objects.all().first()

<Student: Regina Johnson>

last() 方法将从 QuerySet 返回最后一个元素。
>>> 
Student.objects.all()

<QuerySet [<Student: Regina Johnson>, <Student: Eva Smith>, <Student: Jessie Smith>, <Student: John David>]>>>> Student.objects.all().last()

<Student: John David>

尽管 QuerySet 类似于列表,可以使用 queryset[0] 之类的索引检索第一个元素,但不能像 queryset[-1] 那样检索最后一个元素。这将引发错误。在这种情况下,last() 方法会派上用场。
>>> 
Student.objects.all()[
0
]

<Student: Regina Johnson>

>>> 
Student.objects.all()[
-1
]    
"Negative indexing is not supported."
AssertionError: Negative indexing 
isnot
 supported.

9、in_bulk()
in_bulk() 接受一个 id 值列表并返回一个字典,将每个 id 映射到具有该 id 的对象实例。如果不将列表传递给 in_bulk() 方法,则将返回所有对象。
假设我只想检索 id 为 1 和 4 的学生,我可以这样做。
>>> 
students = Student.objects.in_bulk([
1
4
])

>>> 
students[
1
].name

'Regina Johnson'
>>> 
students[
4
].name

'Jessie Smith'
然后我可以使用 id 作为索引访问该对象。
10、explain()
此方法返回 QuerySet 执行计划的字符串。用于分析查询性能
>>> 
Student.objects.filter(pk=
1
).explain()

'2 0 0 SEARCH TABLE student_student USING INTEGER PRIMARY KEY (rowid=?)'
写在最后,希望这篇文章对大家有帮助。
文章转载:Python运维技术
(版权归原作者所有,侵删)
点击下方“阅读原文”查看更多
继续阅读
阅读原文