社区所有版块导航
Python
python开源   Django   Python   DjangoApp   pycharm  
DATA
docker   Elasticsearch  
aigc
aigc   chatgpt  
WEB开发
linux   MongoDB   Redis   DATABASE   NGINX   其他Web框架   web工具   zookeeper   tornado   NoSql   Bootstrap   js   peewee   Git   bottle   IE   MQ   Jquery  
机器学习
机器学习算法  
Python88.com
反馈   公告   社区推广  
产品
短视频  
印度
印度  
Py学习  »  Django

Django ORM 中常用的方操作

马哥Linux运维 • 3 年前 • 588 次点击  

我们都知道 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 文件:

class Student(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

学生表与学校表有外键关系。

class School(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
]>

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

>>> queryset = Student.objects.exclude(name='Eva Smith')
>>> queryset
]>

从查询的结果可以看到,已从查询集中排除

2、values()

下一个方法是 values() 方法。此方法返回 Python 字典,而不是 QuerySet 对象。

>>> Student.objects.values()'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')'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')1, 'Regina Johnson'), (3'Eva Smith'), (4'Jessie Smith'), (5'John David')]>

如果我们只需要一个单一的值,比如一个列表而不是一个元组,我们可以将一个额外的参数 flat=True 传递给 values_list 方法。如果我只想将名称作为列表,可以做这样的事情。

>>> Student.objects.values_list('name', flat=True)'Regina Johnson', 'Eva Smith''Jessie Smith''John David']>

注意:这仅适用于单个字段。如果提供多个字段,则会出现错误。

>>> Student.objects.values_list('id''name', flat=True)
TypeError: 'flat' is not valid when values_list is called with more than one field.

4、select_related()

这是我非常喜欢的方法之一。正如我所说,我的学生表与学校表有外键关系。所以为了从学生那里检索学校,我可以这样查询。

>>> student = Student.objects.get(pk=1)
>>> student.school

首先,使用学生 ID 查询学生表以获取特定学生。然后再次为了获得学校,我们执行额外的数据库查找。

注意:每个外键关系都需要额外的数据库查找。

对于我们的简单示例,这不是问题,但是在具有许多外键关系的大型数据库中,数据库的负载可能会令人望而却步。

我们可以使用 select_related() 通过在第一次命中数据库时检索所有相关数据来提高数据库性能。

>>> student = Student.objects.select_related('school').get(pk=1)
>>> student.school # school has already been retrieved. Database is not hit again.

在这种情况下,学校数据是在进行第一次查询时从预取数据中检索出来的,而不是再次查询数据库。

5、order_by()

order_by() 方法更改了 QuerySet 的默认顺序。默认情况下,排序基于主键(id)字段。如果我希望我的 QuerySet 根据名称排序,我可以将名称字段提供给 order_by() 方法。如果我希望我的 QuerySet 根据名称升序排序,我可以做这样的事情.

>>> Student.objects.order_by('name')]>
如果我想按降序排列名称,我可以像这样查询数据库。

>>> Student.objects.order_by('-name')]>

字段名称的符号将起作用。

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()
]>>>> Student.objects.all().first()

last() 方法将从 QuerySet 返回最后一个元素。

>>> Student.objects.all()
]>>>> Student.objects.all().last()

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

>>> Student.objects.all()[0]

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

9、in_bulk()

in_bulk() 接受一个 id 值列表并返回一个字典,将每个 id 映射到具有该 id 的对象实例。如果不将列表传递给 in_bulk() 方法,则将返回所有对象。

假设我只想检索 id 为 1 和 4 的学生,我可以这样做。

>>> 
students = Student.objects.in_bulk([14])
>>> 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运维技术
(版权归原作者所有,侵删)

点击下方“阅读原文”查看更多

Python社区是高质量的Python/Django开发社区
本文地址:http://www.python88.com/topic/120164
 
588 次点击