zoukankan      html  css  js  c++  java
  • 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

  • 相关阅读:
    异常以及异常处理框架探析
    ArcGis Server10 for java初试
    C#制作鹰眼全过程(带注释)
    flex remoteobject 因默认设置而调用失败
    ExecutorService.submit(Callable).get()不并发执行
    学习《The Flex, Spring, and BlazeDS full stack》-1
    java.lang.NoSuchMethodError: org.hibernate.mapping.SimpleValue.<init>(Lorg/hibernate/mapping/Table;)V
    用内置jetty运行项目struts2提示找不到Action
    二分查找
    排序
  • 原文地址:https://www.cnblogs.com/qingqinxu/p/11045312.html
Copyright © 2011-2022 走看看