day45 ORM【object Relational Mapper】、sqlalchemy操作

day45 ORM【object Relational Mapper】、sqlalchemy操作

一、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

相关推荐