一、ORM的定义与表关系
1.定义
ORM
,全称Object Relational Mapping
,中文叫做对象关系映射,通过ORM我们可以通过类的方式去操作数据库。
2.外键
在MySQL中,表有两种引擎,一种是InnoDB,另外一种是myisam。如果使用的是InnoDB引擎,是支持外键约束的。外键的存在使得ORM框架在处理表关系的时候异常的强大。
如下面两个表:
class User(models.Model):
username = models.CharField(max_length=20)
password = models.CharField(max_length=100)
class Article(models.Model):
title = models.CharField(max_length=100)
content = models.TextField()
author = models.ForeignKey("User",on_delete=models.CASCADE)
类定义为class ForeignKey(to,on_delete,\*\*options)
。第一个参数是引用的是哪个模型,第二个参数是在使用外键引用的模型数据被删除了,这个字段该如何处理,比如有CASCADE
、SET_NULL
、PROTECT
、SET_DEFAULT
、SET()
、DO_NOTHING
等。
3.表关系
3.1一对多:
实现方式:一对多或者多对一,都是通过ForeignKey来实现的。
user = User.objects.first()
# 获取第一个用户的用户名
username = user.username
# 获取第一个用户写的所有文章
articles = user.article_set.all()
如果不想使用模型名字小写_set的方式,想要使用其他的名字,那么可以在定义模型的时候指定related_name
。
例如:
class Article(models.Model):
title = models.CharField(max_length=100)
content = models.TextField()
# 传递related_name参数,以后在方向引用的时候使用articles进行访问
author = models.ForeignKey("User",on_delete=models.SET_NULL,null=True,related_name='articles')
于是获取第一个用户写的所有文章可以
articles = user.articles.all()
3.2一对一
实现方式:Django为一对一提供了一个专门的Field叫做OneToOneField
来实现一对一操作。
3.3多对多
实现方式:Django为这种多对多的实现提供了专门的Field叫做ManyToManyField
。
二、ORM的查询操作需要注意的地方
1. 根据关联的表进行查询:
假如现在有两个ORM模型,一个是Article,一个是Category。比如想要获取文章标题中包含"hello"的所有的分类。那么可以通过以下代码来实现:
categories = Category.object.filter(article__title__contains("hello"))
2. 聚合函数:
以使用聚合函数来提取数据,通过aggregate方法实现。使用方法如下所示:
from django.db.models import Avg
result = Book.objects.aggregate(Avg('price'))
print(result)
>>>{"price__avg":23.0}
result1 = Book.objects.aggregate(my_avg=Avg('price'))
print(result1)
>>>{"my_avg":23}
其中price__avg
的结构是根据field__avg
规则构成的。如果想要修改默认的名字,那么可以将Avg
赋值给一个关键字参数。
aggregate和annotate的区别:
from djang.db.models import Sum
result = Book.objects.annotate(total=Sum("bookstore__price")).values("name","total")
比如以上Sum
的例子,如果使用的是annotate
,那么将在每条图书的数据上都添加一个字段叫做total
,计算这本书的销售总额。而如果使用的是aggregate
,那么将求所有图书的销售总额。
aggregate
:返回使用聚合函数后的字段和值。
annotate
:在原来模型字段的基础之上添加一个使用了聚合函数的字段,并且在使用聚合函数的时候,会使用当前这个模型的主键进行分组(group by)。
3. F表达式与Q表达式:
示例代码如下:
from djang.db.models import F, Q
Employee.object.update(salary=F("salary")+1000)
books = Book.objects.filter(Q(price__lte=10) | Q(rating__lte=9))
F表达式和Q表达式都用于优化ORM的流程,不需要先把数据从数据库提取出来,操作完之后再保存回去,而是直接执行SQL语句。
当只是动态地获取某个数据或是将它进行简单的操作是,用F表达式。
当需要用到 | 、&和~(非)等复杂查询操作时,选择Q表达式。