一、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)
正向查询:通过自己类的外键字段查到另外一张表的内容
res = models.UserInfo.objects.all() for row in res: print(row.name, row.ut.title)
反向查询:本表UserType中没有外键字段,但是在另外一张表Userinfo中有一个外键的字段ut关连到本表了,可以通过小写表名userinfo_set查到部门有哪些人
res = models.UserType.objects.all() for row in res: print(row.title, row.userinfo_set.all())
神奇的下划线跨表查询:因为在.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': '市场部'}
神奇的下划线反向查询:本表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'}
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') ]
查和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
查和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
查和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'}]>
----------------------------------------------------------------------------------------------------------------
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)
--- 给自动生成的表添加【如果重复了不会再添加】
【自己写的第三张表新增数据: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]) # 添加多个
-- 给自动生成的表重置数据
obj = models.Boy.objects.filter(name="zekai").first() obj.g.set([1])
--- 自动生成的表的查询
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 淑芬
--- 自动生成的表的删除【将某个对象对应的数据全部清除】
res = models.Boy.objects.filter(name="jerry").first() res.g.clear()
自己写的与自动生成,应该用哪个?
ManyToManyField 只能生成两个字段,【boy_id 和 girl_id】
可以半自动写一个,不用反向查询,又可以生成多个字段
DB frist: 先有DB, 再有后续的操作
Code first : 先有代码,通过代码创建DB