Django ORM查询
在本教程中,我们将对Django ORM查询进行全面讨论,以及如何使用它们来操作数据。
Django ORM是Django的最佳工具之一,对于执行与数据库相关的任务起着非常重要的作用。它以一种大多数据库无关的方式提供与数据库的抽象。
Django ORM包括易于使用的抽象。它保持 “简单的事情易做,困难的事情可行。”
在这里,我们将详细解释每个ORM查询,并查看它们关联的SQL查询。
使用模型在数据库中创建表
首先,我们将使用Django模型创建一个包含一些数据的示例数据库,并在该数据库上运行查询。
model.py
# Create your models here.
class Student(models.Model):
username = models.CharField(max_length=20)
first_name = models.CharField(max_length=30)
last_name = models.CharField(max_length=30)
mobile = models.CharField(max_length=10)
email = models.EmailField()
def __str__(self):
return "%s %s" % (self.first_name, self.last_name)
然后执行以下命令。
python manage.py makemigrations
python manage.py migrate
我们准备运行这个查询。
如何从表(Model)中获取所有记录
我们有一个叫做 Student 的模型。 为了从模型中获取所有记录,我们将使用 Student.objects.all() 。 为此,请打开Django shell运行查询。
>>> from sampleapp.models import Student
>>> queryset = Student.objects.all()
>>> queryset
, , , , , ]>
你可能会想知道 Django ORM 是如何执行我们的查询或者我们编写的代码对应的查询。获取SQL查询相当简单,我们只需使用 str() 并传递 查询对象 和查询即可。
相应的SQL查询
>>> str(queryset.query)
'SELECT "sampleapp_student"."id", "sampleapp_student"."username", "sampleapp_student"."first_name", "sampleapp_student"."last_name", "sampleapp_student"."mobile", "sampleapp_student"."email" FROM "sampleapp_student"'
如何向表(模型)中添加记录
我们将使用 Student.objects.create() 函数,并将字段及其值作为参数传递。让我们看下面的示例。
>>> queryset = Student.objects.create(username = 'rahul20', first_name = 'Rahul', last_name = 'Shakya', mobile = '77777', email = 'rahul@gmail.com')
>>> queryset.save()
请注意,我们需要在查询对象上使用 .save() 方法将新创建的记录保存在表中,否则它将不会显示在数据库中。
从查询集中检索单个对象
假设我们需要从查询集中获取特定对象以匹配结果。我们可以使用 get() 方法来完成这个操作。get()方法直接返回单个对象。让我们看下面的例子。
示例-
>>> from sampleapp.models import Student
>>> queryset = Student.objects.get(pk = 1)
>>> queryset
示例 – 2
>>> queryset = Student.objects.get(mobile = 22222)
>>> queryset
正如我们在两个示例中看到的那样,我们得到的是单个对象而不是单个对象的查询集。如果没有结果匹配查询, get() 将引发 DoesNotExist 异常。另一方面,如果有多个字段匹配,它将引发 MultipleObjectReturned 异常,这是模型类本身的属性。
筛选记录
在前面的示例中,由 all() 返回的 QuerySet 描述了数据库表中的所有记录。但是有时候,我们需要选择完整对象集的子集,并且可以通过添加 filter 条件来实现。
在下面的示例中,我们将获取以 R 开头的姓氏的数据。
>>> queryset = Student.objects.filter(first_name__startswith = 'R')
>>> queryset
, ]>
>>> str(queryset.query)
'SELECT "sampleapp_student"."id", "sampleapp_student"."username", "sampleapp_student"."first_name", "sampleapp_student"."last_name", "sampleapp_student"."mobile", "sampleapp_student"."email" FROM "sampleapp_student" WHERE "sampleapp_student"."first_name" LIKE R% ESCAPE \'\\\''
注意 – get()方法和filter()方法的区别在于,filter()方法返回对象的查询集,而get()方法返回单个对象。
使用exclude()方法
它返回一个新的 查询集 ,其中包含不匹配给定查找参数的对象。换句话说,它根据查找条件排除了记录。让我们理解以下示例。
>>> queryset = Student.objects.exclude(first_name__startswith = 'R')
>>> queryset
输出结果:
, , , , ]>
如何在Django ORM中进行OR查询
当我们需要使用两个或多个条件进行记录过滤时,会执行OR操作。在下面的示例中,我们将获取名字以’A’开头且姓以’M’开头的学生。
Django允许我们有两种方法来实现这一点。
- queryset_1 | queryset_2
- filter(Q(
) | Q(
>>> queryset = Student.objects.filter(first_name__startswith = 'R') | Student.objects.filter(last_name__startswith = 'S')
>>> queryset
, , , , ]>
我们获取名字以 ‘A’ 开头、姓以 ‘S’ 开头的学生详细信息。
以下是相应的OR操作符的SQL查询。
>>> str(queryset.query)
'SELECT "sampleapp_student"."id", "sampleapp_student"."username", "sampleapp_student"."first_name", "sampleapp_student"."last_name", "sampleapp_student"."mobile", "sampleapp_student"."email" FROM "sampleapp_student" WHERE ("sampleapp_student"."first_name" LIKE R% ESCAPE \'\\\' OR "sampleapp_student"."last_name" LIKE S% ESCAPE \'\\\')'
如何在Django ORM中进行AND查询
当我们需要与两个或多个条件匹配的记录时,需要进行AND操作。在下面的例子中,我们将获得名字以’P’开头且姓以’S’开头的学生。
Django允许我们以三种方式实现这一点:
- queryset_1 & queryset_2
- filter(
, ) - filter(Q(condition_1) & Q(condition_2))
>>> queryset = Student.objects.filter(first_name__startswith = 'P') & Student.objects.filter(last_name__startswith = 'S')
>>> queryset
]>
只有一个对象满足给定的条件。
我们还可以使用以下查询。
queryset2 = User.objects.filter( first_name__startswith='A', last_name__startswith='S' )
或者
queryset3 = User.objects.filter(Q(first_name__startswith='R') & Q(last_name__startswith='D') )
所有查询将产生相同的结果。
一次性创建多个对象
有时我们想要一次性创建多个对象。假设我们想要立即创建新对象,而不想对数据库运行多个查询。Django ORM提供了 bulk_create 来一次性创建多个对象。
>>> Student.objects.all().count()
7
让我们一次查询中创建多条记录。
Student.objects.bulk_create([Student(first_name = 'Jai', last_name = 'Shah', mobile = '88888', email = 'shah@reddif.com'),Student(first_name = 'Tarak', last_name = 'Mehta', mobile = '9999', email = 'tarak@reddif.com'), Student(first_name = 'SuryaKumar', last_name = 'Yadav', mobile = '00000', email = 'yadav@reddif.com')])
[, , ]
现在,我们的数据库表将会更新。bulk_create接受一个未保存对象的列表。
>>> Student.objects.all().count()
10
限制查询集
我们可以使用Python的 列表切片 语法来限制查询集的数量。这相当于SQL中的 LIMIT 和 OFFSET 子句的操作。让我们看一下下面的查询。
>>> Student.objects.all()[:4]
, , , ]>
以下查询将返回 第一个 记录到 第五个 记录。
>>> Student.objects.all()[1:6]
, , , , ]>
不支持负索引。但是,我们可以在QuerySets中使用 步长 。
>>> Student.objects.all()[:10:2]
[, , , , ]
要获取单个记录,我们可以执行以下操作。
>>> Student.objects.all()[0]
如何按升序或降序对QuerySets进行排序
Django提供了 order_by 方法来对查询结果进行排序。该方法接受 字段名 作为参数,用于对结果进行升序或降序排序。让我们看下面的例子。
示例- 升序排列
>>> from sampleapp.models import Student
>>> Student.objects.all().order_by('mobile')
, , , , , , , , , ]>
对于降序排列,我们将在查询字段之前不使用“-”。
>>> from sampleapp.models import Student
>>> Student.objects.all().order_by('-mobile')
, , , , , , , , , ]>
我们还可以在 order_by 函数中传递多个字段。
>>> Student.objects.all().order_by('first_name','-mobile')
, , , , , , , , , ]>
如何在相关模型上按照外键排序
现在,我们将学习如何在关联模型中对数据进行排序。我们创建了另一个模型叫做 Teacher ,它是 Student 模型的关联模型。
模型
class Teacher(models.Model):
teacher_name = models.CharField(max_length=200)
def __str__(self):
return f'{self.teacher_name}'
class Student(models.Model):
username = models.CharField(max_length=20)
first_name = models.CharField(max_length=30)
last_name = models.CharField(max_length=30)
mobile = models.CharField(max_length=10)
email = models.EmailField()
teacher_name = models.ForeignKey(Teacher, blank = True, null = True, on_delete= models.CASCADE)
我们已经添加了教师的姓名,每个教师与学生关联。现在我们想要按照每个 教师姓名 内的学生 对学生进行排序 。我们可以按照以下方式操作。
>>> Student.objects.all().order_by('teacher__id', 'first_name')
, , , , , , , , , ]>
重要的字段查找
查询字段查找就是指定与SQL中的WHERE子句相同的条件。它们被作为关键字参数传递给QuerySet方法,例如 filter() 、 exclude() 和 get() 。
示例 –
Student.objects.filter(first_name__startswith = 'Ritesh')
]>
这与以下的SQL查询相同
Select * from Student where first_name = "Ritesh"
让我们了解一些重要的查找。
- exact
根据搜索返回精确结果。
>>> Student.objects.get(first_name__exact = 'Arpita')
在双下划线之后应使用Lookup: __ 。我们可以使用不区分大小写的版本,称为 iexact 。
- contains
它用于区分大小写的测试。让我们看下面的例子。
>>> from sampleapp.models import Student
>>> Student.objects.filter(last_name__contains = 'Shar')
, , ]>
如果我们将SQL查询翻译成中文,它会看起来像下面这样。
SELECT ... WHERE last_name LIKE '%Shar%';
也有一种叫做 icontains 的案例激励版本。
如何在Django中执行连接操作
SQL连接在两个或多个表之间基于共同字段结合数据或行。我们可以以多种方式执行连接操作。让我们理解以下示例。
>>> q = Student.objects.select_related('teacher')
>>>q
, , , , , , , , , ]>
>>>print(q.query)
SELECT "sampleapp_student"."id", "sampleapp_student"."username", "sampleapp_student"."first_name", "sampleapp_student"."last_name", "sampleapp_student"."mobile", "sampleapp_student"."email", "sampleapp_student"."teacher_id", "sampleapp_teacher"."id", "sampleapp_teacher"."teacher_name" FROM "sampleapp_student" LEFT OUTER JOIN "sampleapp_teacher" ON ("sampleapp_student"."teacher_id" = "sampleapp_teacher"."id")
如何在Django ORM中分组记录
Django ORM通过使用聚合函数(如Max、Min、Avg和Sum)提供分组功能。有时我们需要从对象中获取聚合值。让我们理解以下示例。
>>> from django.db.models import Avg, Max, Min, Sum, Count
>>> Student.objects.all().aggregate(Avg('id'))
{'id__avg': 5.5}
>>> Student.objects.all().aggregate(Min('id'))
{'id__min': 1}
>>> Student.objects.all().aggregate(Max('id'))
{'id__max': 10}
>>> Student.objects.all().aggregate(Sum('id'))
{'id__sum': 55}
如何使用Django ORM执行类似于truncate的操作
在SQL中,truncate的意思是清除表中的数据以供将来使用。Django没有提供内置的方法来截断表,但我们可以使用 delete() 方法来获得类似的结果。让我们来理解以下示例。
>>> Student.objects.all().count()
10
>>> Student.objects.all().delete()
(10, {'sampleapp.Student': 10})
>>> Student.objects.all().count()
0
>>> Student.objects.all()
如果要删除单个对象实例,您需要在该模型的个别实例上调用 delete() 方法。我们已经调用了模型上的 delete() 方法,所以它删除了整个数据。
如何获取数据的并集
并集意味着获取在两个查询集中都存在的记录。让我们看看如何做到这一点。
>>> q1 = Student.objects.filter(id__gte = 15)
>>> q1
, ]>
>>> q2 = Student.objects.filter(id__lte = 15)
>>> q2
, , , , ]>
>>> q1.union(q2)
, , , , , ]>
什么是null=True和blank=True的区别
在Django中,我们经常使用null和blank,默认情况下它们的值为False。这两个值都用于字段级别,在我们想要保持字段为null或空白的情况下使用。这两个值似乎相似,但在使用上有所不同。
如果 null=True 表示字段值被设为NULL,即没有数据。它基本上是用于数据库列值。
date = models.DateTimeField(null=True)
空格=True指定字段在表单中是否为必填项。
title = models.CharField(blank=True) // title can be kept blank. In the database ("") will be stored.
如果我们设置了 null=True blank=True ,这意味着该字段在任何情况下都是可选的。
teacher = models.ForeignKey(null=True, blank=True) // The exception is CharFields() and TextFields(), which in Django are never saved as ?→NULL. Blank values are stored in the DB as an empty string ('').
结论
在这个教程中,我们学习了一些重要的ORM查询。Django ORM是一个强大的工具,也是Django的一个关键支柱。Django自带名为SQLite的内置数据库。我们描述了ORM查询,其与SQL查询具有相同的作用。