Diango教程-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
我们准备运行查询。
如何从表(模型)中获取所有记录
我们有一个名为“学生”的模型。要从模型中获取所有记录,我们将使用Student.objects.all()。为此,请打开 Django shell 来运行查询。
>>> from sampleapp.models import Student
>>> queryset = Student.objects.all()
>>> queryset
<QuerySet [<Student: Ritesh Tiwari>, <Student: Yash Sharma>, <Student: Arpita Sharma>, <Student: Prince Sharma>, <Student: Megha Bhardwaj>, <Student: Akash Mishra>]>
您可能想知道Django ORM如何执行我们的查询,或者我们正在编写的代码对应的查询是什么。获取SQL查询非常简单,我们需要使用str()并将queryset 对象与查询一起传递。
对应的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
<Student: Ritesh Tiwari>
示例 - 2
>>> queryset = Student.objects.get(mobile = 22222)
>>> queryset
<Student: Yash Sharma>
正如我们在两个示例中看到的,我们得到的是单个对象,而不是单个对象的查询集。如果没有结果与查询匹配,get()将引发DoesNotExist异常。另一方面,如果存在多个字段匹配,则会引发 MultipleObjectReturned ,这是模型类本身的属性。
过滤记录
在前面的示例中,all()返回的QuerySet描述了数据库表中的所有记录。但有时,我们需要选择完整对象集合的子集,这可以通过添加过滤条件来完成。
在下面的示例中,我们将获取名字以R开头的数据。
>>> queryset = Student.objects.filter(first_name__startswith = 'R')
>>> queryset
<QuerySet [<Student: Ritesh Tiwari>, <Student: Rahul Shakya>]>
>>> 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() 方法返回单个对象。
使用 except() 方法
它返回一个新的QuerySet,其中包含与给定查找参数不匹配的对象。换句话说,它根据查找条件排除了记录。让我们理解下面的例子。
>>> queryset = Student.objects.exclude(first_name__startswith = 'R')
>>> queryset
输出:
,,,,]>
如何在 Django ORM 中进行 OR 查询?
当我们需要两个或多个条件的记录过滤时,执行OR操作。在下面的示例中,我们将获取名字以“A”开头且姓氏以“M”开头的学生。
Django 允许我们通过两种方式做到这一点。
- queryset_1 |queryset_2
- filter(Q(<condition_1>) | Q(<condition_2>
>>> queryset = Student.objects.filter(first_name__startswith = 'R') | Student.objects.filter(last_name__startswith = 'S')
>>> queryset
<QuerySet [<Student: Ritesh Tiwari>, <Student: Yash Sharma>, <Student: Arpita Sharma>, <Student: Prince Sharma>, <Student: Rahul Shakya>]>
我们获取学生详细信息,其中名字以“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 允许我们通过三种方式做到这一点。
- 查询集_1 和查询集_2
- 过滤器(<条件_1>, <条件_2>)
- 过滤器(Q(条件_1) & Q(条件_2))
>>> queryset = Student.objects.filter(first_name__startswith = 'P') & Student.objects.filter(last_name__startswith = 'S')
>>> queryset
<QuerySet [<Student: Prince Sharma>]>
只有一个对象满足给定条件。
我们还可以使用以下查询。
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')])
[<Student: Jai Shah>, <Student: Tarak Mehta>, <Student: SuryaKumar Yadav>]
现在,我们的数据库表将更新。bulk_create获取未保存对象的列表。
>>> Student.objects.all().count()
10
限制查询集
我们可以使用 Python列表的切片语法来设置查询集的限制。这与 SQL 的LIMIT和OFFSET子句的操作等效。让我们看看下面的查询。
>>> Student.objects.all()[:4]
<QuerySet [<Student: Ritesh Tiwari>, <Student: Yash Sharma>, <Student: Arpita Sharma>, <Student: Prince Sharma>]>
下面的查询将返回第一条记录到第五条记录。
>>> Student.objects.all()[1:6]
<QuerySet [<Student: Yash Sharma>, <Student: Arpita Sharma>, <Student: Prince Sharma>, <Student: Megha Bhardwaj>, <Student: Akash Mishra>]>
不支持负索引。但是,我们可以使用QuerySets 中的步骤。
>>> Student.objects.all()[:10:2]
[<Student: Ritesh Tiwari>, <Student: Arpita Sharma>, <Student: Megha Bhardwaj>, <Student: Rahul Shakya>, <Student: Tarak Mehta>]
为了获取单个记录,我们可以执行以下操作。
>>> Student.objects.all()[0]
<Student: Ritesh Tiwari>
如何按升序或降序对查询集进行排序?
Django 提供了order_by方法来对查询集进行排序。此方法采用我们想要对结果进行排序(升序和降序)的字段名称。让我们看下面的例子。
示例 - 升序
>>> from sampleapp.models import Student
>>> Student.objects.all().order_by('mobile')
<QuerySet [<Student: SuryaKumar Yadav>, <Student: Ritesh Tiwari>, <Student: Yash Sharma>, <Student: Arpita Sharma>, <Student: Prince Sharma>, <Student: Megha Bhardwaj>, <Student: Akash Mishra>, <Student: Rahul Shakya>, <Student: Jai Shah>, <Student: Tarak Mehta>]>
对于降序排列,我们将在查询字段前使用 Not '-'。
>>> from sampleapp.models import Student
>>> Student.objects.all().order_by('-mobile')
<QuerySet [<Student: Tarak Mehta>, <Student: Jai Shah>, <Student: Rahul Shakya>, <Student: Akash Mishra>, <Student: Megha Bhardwaj>, <Student: Prince Sharma>, <Student: Arpita Sharma>, <Student: Yash Sharma>, <Student: Ritesh Tiwari>, <Student: SuryaKumar Yadav>]>
我们还可以在order_by函数中传递多个字段。
>>> Student.objects.all().order_by('first_name','-mobile')
<QuerySet [<Student: Akash Mishra>, <Student: Arpita Sharma>, <Student: Jai Shah>, <Student: Megha Bhardwaj>, <Student: Prince Sharma>, <Student:
Rahul Shakya>, <Student: Ritesh Tiwari>, <Student: SuryaKumar Yadav>, <Student: Tarak Mehta>, <Student: Yash Sharma>]>
如何对相关模型(带有外键)的字段进行排序?
现在,我们将学习如何对关系模型中的数据进行排序。我们创建另一个名为Teacher的模型,它是Student模型的相关模型。
Models
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')
<QuerySet [<Student: Prince Sharma>, <Student: Ritesh Tiwari>, <Student: SuryaKumar Yadav>, <Student: Tarak Mehta>, <Student: Arpita Sharma>, <Student: Megha Bhardwaj>, <Student: Jai Shah>, <Student: Rahul Shakya>, <Student: Yash Sharma>, <Student: Akash Mishra>]>
重要字段查找
查询字段查找只不过是指定与 SQL WHERE子句相同的条件。它们被声明为 QuerySet 方法(例如filter()、exclusive()和get())的关键字参数。
例子
Student.objects.filter(first_name__startswith = 'Ritesh')
<QuerySet [<Student: Ritesh Tiwari>]>
这与以下 SQL 查询相同
Select * from Student where first_name = "Ritesh"
让我们了解一些重要的查找。
- 精确的
它根据搜索返回准确的结果。
>>> Student.objects.get(first_name__exact = 'Arpita')
<Student: Arpita Sharma>
应该在 __ 双下划线之后使用查找。我们可以使用名为 iexact 的不区分大小写的版本。
- 包含
它用于区分大小写的测试。让我们看下面的例子。
>>> from sampleapp.models import Student
>>> Student.objects.filter(last_name__contains = 'Shar')
<QuerySet [<Student: Yash Sharma>, <Student: Arpita Sharma>, <Student: Prince Sharma>]>
如果我们翻译 SQL 查询,它将如下所示。
SELECT ... WHERE last_name LIKE '%Shar%';
还有一个称为icontains 的案例激励版本。
如何在 Django 中执行连接操作
SQL 连接根据两个或多个表之间的公共字段组合来自两个或多个表的数据或行。我们可以通过多种方式执行连接操作。让我们理解下面的例子。
>>> q = Student.objects.select_related('teacher')
>>>q
<QuerySet [<Student: Ritesh Tiwari>, <Student: Yash Sharma>, <Student: Arpita Sharma>, <Student: Prince Sharma>, <Student: Megha Bhardwaj>, <Student: Akash Mishra>, <Student: Rahul Shakya>, <Student: Jai Shah>, <Student: Tarak Mehta>, <Student: SuryaKumar Yadav>]>
>>>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 执行类似截断的操作?
SQL中的截断意味着清除表数据以供将来使用。Django没有提供内置的方法来截断表,但是我们可以使用delete()方法来获得类似的结果。让我们理解下面的例子。
>>> Student.objects.all().count()
10
>>> Student.objects.all().delete()
(10, {'sampleapp.Student': 10})
>>> Student.objects.all().count()
0
>>> Student.objects.all()
<QuerySet []>
如果要删除单个对象实例,则需要对该模型的各个实例调用delete()方法。我们在模型上调用了delete()方法,因此它删除了整个数据。
如何获得数据的并集
联合意味着获取两个查询集中共有的记录。让我们看看如何做到这一点。
>>> q1 = Student.objects.filter(id__gte = 15)
>>> q1
<QuerySet [<Student: Megha Bhardwaj>, <Student: Akash Mishra>]>
>>> q2 = Student.objects.filter(id__lte = 15)
>>> q2
<QuerySet [<Student: Ritesh Tiwari>, <Student: Yash Sharma>, <Student: Arpita Sharma>, <Student: Prince Sharma>, <Student: Megha Bhardwaj>]>
>>> q1.union(q2)
<QuerySet [<Student: Ritesh Tiwari>, <Student: Yash Sharma>, <Student: Arpita Sharma>, <Student: Prince Sharma>, <Student: Megha Bhardwaj>, <Student: Akash Mishra>]>
null=True 和 Blank=True 有什么区别?
在Django中,我们经常使用null和blank,默认情况下它们的值为False。这两个值都在字段级别起作用,我们希望将字段保留为空或空白。这两个值看似相似,但用途不同。
如果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 查询相同。