在这里介绍了ORM的概念和优缺点,和基于ORM的数据库操作之增删改查。以及一对一操作,一对多操作,多对多操作。
ORM的概念
ORM:Object Relational Mapping(对象关系映射)
让我们从O/R开始。字母O起源于”对象”(Object),而R则来自于”关系”(Relational)。几乎所有的程序里面,都存在对象和关系数据库。在业务逻辑层和用户界面层中,我们是面向对象的。当对象信息发生变化的时候,我们需要把对象的信息保存在关系数据库中。
当你开发一个应用程序的时候(不使用O/R Mapping),你可能会写不少数据访问层的代码,用来从数据库保存,删除,读取对象信息,等等。你在DAL中写了很多的方法来读取对象数据,改变状态对象等等任务。而这些代码写起来总是重复的。
ORM解决的主要问题是对象关系的映射。域模型和关系模型分别是建立在概念模型的基础上的。域模型是面向对象的,而关系模型是面向关系的。一般情况下,一个持久化类和一个表对应,类的每个实例对应表中的一条记录,类的每个属性对应表的每个字段。
ORM技术特点
提高了开发效率。由于ORM可以自动对Entity对象与数据库中的Table进行字段与属性的映射,所以我们实际可能已经不需要一个专用的、庞大的数据访问层。
ORM提供了对数据库的映射,不用sql直接编码,能够像操作对象一样从数据库获取数据。
ORM的缺点
ORM的缺点是会牺牲程序的执行效率和会固定思维模式。
从系统结构上来看,采用ORM的系统一般都是多层系统,系统的层次多了,效率就会降低。ORM是一种完全的面向对象的做法,而面向对象的做法也会对性能产生一定的影响。 但ORM是一种工具,工具确实能解决一些重复,简单的劳动。这是不可否认的。
在models里面创建一张表,下面的都是基于这张表的操作。
class UserInfo(models.Model): |
导入
from blog import models |
ORM之增(create,save)
这里推荐使用第三种方式# 增
# 第一种方式
models.UserInfo.objects.create(username='zsy1', sex='girl', mail='love.com')
# 第二种方式
obj = models.UserInfo(username='zsy2', sex='girl', mail='love.com')
obj.save()
# 第三种方式
user1 = {'username': 'zsy3', 'sex': 'girl', 'mail': 'love.com'}
models.UserInfo.objects.create(**user1)
return HttpResponse("已增加")
ORM之删
# 删 |
ORM之改
推荐使用update# 改
# 方式1 update()
models.UserInfo.objects.all().update(mail=8888)
models.UserInfo.objects.filter(id=12).update(mail=888888)
# 方式2 obj.save()
user2 = models.UserInfo.objects.get(id=12)
user2.sex = 'woman'
user2.save()
return HttpResponse("已修改")
ORM之查
# 查 |
上面的一对一翻篇了,接下来我们学习下一对多和多对多,而我们又可以把一对多,多对多,分为正向和反向查找两种方式。
这里我们创建了两张表,在models中:
class UserType1(models.Model): |
之后再命令行执行:python manage.py makemigrations
python manage.py migrate
这样我们就创建了两张空表:
正查与反查
这里ForeignKey
在 UserInfo
表中
正向查找:如果从UserInfo表开始向其他的表进行查询,这个就是正向查询。
反向查询:如果从UserType表去查询其他的表这个就是反向操作。
ORM之一对多
增加数据
这里对user_type赋值,有两种方法:
第一种方式:再次查询数据库,不推荐
user_type = models.UserInfo1.objects.filter(id=1).first() |
第二种方式:通过 外键字段_id
user_tyoe_id = 1 |
所以我们使用第二种创建数据:
dic = {'username': 'mosson', 'age': 18, 'user_type_id': 1} |
查询数据
获取到的数据类型本质上都是 queryset
类型,
类似于列表,
内部有3种表现形式(对象,字典,列表)
# <QuerySet [<表名: 表 object>, <表名: 表 object>]> |
注意:这里使用双下划线跨表取键值
# <QuerySet [{'xx': 'xx', 'xx': x}, {'xx': 'x', 'xx': x}]> |
# <QuerySet [('xx', x), ('xx', x)]> |
正向查询例子
通过UserInfo1查询:ret = models.UserInfo1.objects.filter(user_type__caption='COO')
print(ret)
for item in ret:
print(item,item.username,item.age,item.user_type.caption)
return HttpResponse("OK")
反向查询
通过UserType1查询:
方法一:ret = models.UserType.objects.filter(caption='COO').values('userinfo__username')
for item in ret:
print(item,type(item))
ret = models.UserType.objects.filter(caption='COO').first() |
总结
正向查找:
- filter(跨表的时候,应该是对象__跨表的字段)
- 获取这个值的时候,拿到了一行数据的时候 line.对象.跨表的字段
反向查找:
- filter(关联这个表的表明) 自动创建和表明相同的对象,通过这个对象__跨表的字段
- line.自动创建和表明相同的对象_set.方法
ORM之多对多
首先需要说明的是:
多对多和一对多没有任何关系
创建
方式一:自定义关系表
class HostToApp(models.Model):
hobj = models.ForeignKey(to='Host',to_field='nid')
aobj = models.ForeignKey(to='Application',to_field='id')方式二:自动创建关系表
表中添加ManyToManyField
class Application(models.Model):
name = models.CharField(max_length=32)
d = models.ManyToManyField("Host")