day45 ORM【object Relational Mapper】、sqlalchemy操作
分类:
IT文章
•
2022-03-29 23:34:04

一、ORM【object Relational Mapper】
回顾一下,之前操作Mysql, 用PYMysql操作mysql
使用pymsql的前提条件:
1.表先建好
2.自己需要手动去写多条SQL语句
改进:
类 --- > 表
实例化 --> 数据
这种思想叫ORM(Object Relationship Mapping) 对象关系映射
基于这种思想开发的产品,python比较出名的ORM框架:SQLAlchemy
二、SQLAlchemy的操作
基本原理:将代码转换成SQL语名执行
安装: pip install SQLAlchemy
使用: SQLAlchemy链接mysql:
底层使用pyMysql 来进行操作的
注意:字符编码,可以在创建数据库的时候设置,也可以在配置文件中设置
create database db3 charset=utf8;
engine = create_engine("mysql+pymysql://root:123@127.0.0.1:3306/db3?charset=utf8", max_overflow=5)
1. 一对多操作数据:
class UserType(models.Model):
title = models.CharField(max_length=32)
class UserInfo(models.Model):
name = models.CharField(max_length=32, null=True)
age = models.CharField(max_length=32, null=True)
ut = models.ForeignKey(to='UserType', null=True)
View Code
正向查询:通过自己类的外键字段查到另外一张表的内容
res = models.UserInfo.objects.all()
for row in res:
print(row.name, row.ut.title)
View Code
反向查询:本表UserType中没有外键字段,但是在另外一张表Userinfo中有一个外键的字段ut关连到本表了,可以通过小写表名userinfo_set查到部门有哪些人
res = models.UserType.objects.all()
for row in res:
print(row.title, row.userinfo_set.all())
View Code
神奇的下划线跨表查询:因为在.all的结果是列表套对象,如果不是.all(), 而是.values('name') 结果是不列表套字典,不能用字典点出东西
res = models.UserInfo.objects.values('name', "ut__title")
for row in res:
print(row)
{'name': 'zekai', 'ut__title': '开发部'}
{'name': 'jerry', 'ut__title': '开发部'}
{'name': 'egon', 'ut__title': '小卖部'}
{'name': 'boby', 'ut__title': '小卖部'}
{'name': 'owen', 'ut__title': '市场部'}
{'name': 'jason', 'ut__title': '市场部'}
View Code
神奇的下划线反向查询:本表UserType中没有外键字段,可以用表名小写加引号
res = models.UserType.objects.values('title', "userinfo__name")
for row in res:
print(row)
{'title': '开发部', 'userinfo__name': 'zekai'}
{'title': '开发部', 'userinfo__name': 'jerry'}
{'title': '小卖部', 'userinfo__name': 'egon'}
{'title': '小卖部', 'userinfo__name': 'boby'}
{'title': '市场部', 'userinfo__name': 'owen'}
{'title': '市场部', 'userinfo__name': 'jason'}
View Code
2. 多对多操作数据:
a.手动创建第三张关联表
class Boy(models.Model):
name = models.CharField(max_length=32, null=True)
class Girl(models.Model):
nick = models.CharField(max_length=32, null=True)
class Love(models.Model):
b = models.ForeignKey(to="Boy", null=True)
g = models.ForeignKey(to="Girl", null=True)
# 联合唯一
class Meta:
unique_together = [
('b', 'g')
]
View Code
查和zekai约会的girl方式一:【先从boy表中查反向love_set到第三张表,再通第三张表的外键字段正向查询g.nick, 跨表到girl表中查询】
# res 一个对象
res = models.Boy.objects.filter(name='zekai').first()
love_obj_list = res.love_set.all() # 反向查询
print(love_obj_list)
# <QuerySet [<Love: Love object>, <Love: Love object>]>
for obj in love_obj_list: # 正向查询
print(obj.g.nick)
rose
boby
View Code
查和zekai约会的girl方式二:【通过love表中的b__name 直接从love表中查zekai,再通过love表对旬跨表到girl表中查nick】
res = models.Love.objects.filter(b__name='zekai').all()
for row in res:
print(row.g.nick)
rose
boby
View Code
查和zekai约会的girl方式三:【love表中的b在boy表中相当于一行数据,g在girl表中相当于是一行数据,可以通过神奇的下划线跨表查询】
res = models.Love.objects.filter(b__name='zekai').values('g__nick')
print(res)
<QuerySet [{'g__nick': 'rose'}, {'g__nick': 'boby'}]>
View Code
----------------------------------------------------------------------------------------------------------------
b. django自动生成第三张表【自己不用写第三张,通过ManyToManyField】, 多对多在任何一张表都可以写
自动生成的第三张表中的表名【app01_boy_g】字段默认为:boy_id girl_id
class Boy(models.Model):
name = models.CharField(max_length=32, null=True)
g = models.ManyToManyField(to="Girl", null=True)
class Girl(models.Model):
nick = models.CharField(max_length=32, null=True)
View Code
--- 给自动生成的表添加【如果重复了不会再添加】
【自己写的第三张表新增数据:models.Love.objects.create(b_id=1, g_id=2)】
# 给zekai添加一个记录
obj = models.Boy.objects.filter(name="zekai").first()
print(obj) # Boy object
obj.g.add(4) # girl的id
obj.g.add(*[2, 3]) # 添加多个
View Code
-- 给自动生成的表重置数据
obj = models.Boy.objects.filter(name="zekai").first()
obj.g.set([1])
View Code
--- 自动生成的表的查询
res = models.Boy.objects.filter(name="jerry").first()
# obj_list = res.g.add(*[1, 2, 3, 4]) 添加多条数据
res = res.g.all()
print(res) #
<QuerySet [<Girl: Girl object>, <Girl: Girl object>, <Girl: Girl object>, <Girl: Girl object>]>
for obj in res:
print(obj.nick)
rose
boby
lili
淑芬
View Code
--- 自动生成的表的删除【将某个对象对应的数据全部清除】
res = models.Boy.objects.filter(name="jerry").first()
res.g.clear()
View Code
自己写的与自动生成,应该用哪个?
ManyToManyField 只能生成两个字段,【boy_id 和 girl_id】
可以半自动写一个,不用反向查询,又可以生成多个字段
DB frist: 先有DB, 再有后续的操作
Code first : 先有代码,通过代码创建DB