zoukankan      html  css  js  c++  java
  • 4、django-ORM

    #前言:ORM(Object Relational Mapping):对象-关系映射#

      1、model与数据库对应关系:

        类----------表

        属性变量-----表字段

        属性对象-----表字段约束

        类实例对象---表记录

      2、单表基本操作:

      DDL就不说了。主要记录下DML语句与orm之间的对比

        增加:

          sql:INSERT 表名(name,age) VALUES ("john", 23);

          orm:类名.objects.create(name="john", age=23)

        查询:

          sql:SELECT * FROM 表名 where age = 23

          orm:类名.objects.filter(age=23)

        修改:

          sql:UPDATE 表名 SET age = 30 WHERE name = "john"

          orm:类名.objects.filter(name="john").update(age=30)

        删除:

          sql:DELETE FROM 表名 WHERE name = "john"

          orm:类名.objects.filter(name="john").delete()

      3、model类的常用字段类型:

        CharField:字符串字段,用于较短的字符串

        IntegerField:整数型

        FloatField:浮点型,需指两个参数。max_digits:最大总位数。decimal_places:小数最大位数。

        AutoField 通常不使用。如果设置primary_key=True则为自定义主键。

        TextField:大容量文本字段

        EmailField:带Email合法性校验的CharField,不接受maxlength参数

        DateField:日期字段

        剩下还有一些不常用给的。CharField大法好。

      

      4、orm常用查询方法:

        1、all():查询所有结果

        2、filter(**kwargs):查询所有符合筛选条件的对象

        3、get(**kwargs):筛选,返回结果有且只有一个,如果筛选的结果超过一个或者没有,则报错

        4、exclude(**kwargs):过滤条件取反

        5、order_by(*field):排序

        6、reverse():反转

        7、count:返回查询到的QuerySet对象数量

        8、first():返回第一条记录

        9、last():返回最后一条记录

        10、exists():如果查询到的QuerySet包含数据就返回True,否则返回False。

        11、distinct():返回结果去重

        12、values(*field):返回一个ValueQuerySet。

      5、基于双下划线的模糊查询:

         类名.objects.filter(price__in=[100,200,300])  # price字段值是否为其中选项之一

         类名.objects.filter(price__gt=[100])  # price字段值是否大于选项

         类名.objects.filter(price__lt=[100])  # price字段值是否小于选项

         类名.objects.filter(price__range=[100,200])  # price字段值是否位于选项区间之内

         类名.objects.filter(title__contains=["john"])  # title字段值是否包含该字符串,区分大小写

         类名.objects.filter(title__icontains=["John"])  # title字段值是否包含该字符串,不区分大小写

         类名.objects.filter(title__startswith=["py"])  # title字段值是否以该字符串开头

      6、多表操作(ForeignKey和ManyToManyField):

        1、一对多ForeignKey操作

          1、添加记录:

            orm:类名.objects.create(name="john", age=23,关联表字段=xx)    # 与单表一样,就是多一个字段

        2、多对多ManyToManyField      

          假设a表与b表多对多,生成了第三张关系表c

           1、添加记录:

            result = a.objects.get(id=1)

            result.b.add(2)

            c表添加一条关联记录。a表id=1,b表id=2

           2、删除记录:

            方式1:

              result = a.objects.get(id=1)

              result.b.remove(2,3)

              c表删除两条关联记录。a表id=1,b表id=2或者b表id=3

            方式2:

              result = a.objects.get(id=1)

              result.b.clear()

              c表所有关于a.id=1的记录全部删除

            方式3:

               result = a.objects.get(id=1)

               result.b.set(4)

              c表删除所有a.id=1的记录。然后插入一条记录a.id=1,b.id=4

        3、中介模型:

          a表与b表。在a表中设置ManyToManyField生成c表的时候,c表默认仅有两个表

          的关联字段,且无法修改。但是在绑定ManyToManyField的时候添加through=“xxx”

          后,则可以进行自定义第三张xxx关联表,随意编辑,django不会自动创建。

         4、跨表查询:

          假设现在有a、b、c、三个表。a跟b一对多,a表设置ForeignKey,a表和c表多对多。

          a表设置ManyToManyField

          ####基于对象(子查询)

            正向查询按字段,反向查询按relate_name,如果没有设置。按照表名小写_set

            a查b -- 正查:

              result = A.object.get(id=1)

              result.b.all()    #因为这里b是多的一方,所以要加all。如果查的是1的一方,则不加。

            b查a -- 反查:

              result = B.object.get(id=1)

              result.a_set     

            ManyToManyField和OneToOneField同理。

          ####基于双下划线(join查询)

            正向查询按字段,反向查询按表名小写

            根据a表id字段查b表的name字段

            A.objects.filter(id=1).values("b__name")   正向查询

            b.object.filter(a_id=1).values("name")    反向查询

            * filter这里也可以结合模糊搜索查询。   

        5、分组查询     

          聚合

            A.objects.all().aggregate(AVG("xxxx"))

          分组

            单表分组:A表有dep字段。按照dep字段分组。求平均薪水

              sql:select dep,AVG(salary) form A group by dep

              orm: A.objects.values("dep").annotate(avg=AVG("salary"))  #annotate前面的是分组字段

              所以一般不用all用value。

            跨表分组:

              方式1:A.objects.value(id).annotate(c=Count("b"))  #根据a表主键分组,count b表主键 返回id和c两个字段

              方式2:A.objects.all.annotate(c=Count("b")).values("c","xxx")

              方式2可以指定返回数据,更加实用

            总结:

              一个复杂的ORM具体样式如下:如用户表和订单表。查询所有姓刘的用户的个人最高单价订单。返回用户姓名和订单中最高的金额,                                   假设user表id与order表cus_id关联

    SELECT
        a.username,
        max( b.prcie ) 
    FROM
        USER AS a
        INNER JOIN ORDER AS b 
    WHERE
        a.id = b.cus_id 
        AND username LIKE "刘%" 
    GROUP BY
        cus_id

              转换成orm就应该如下:

    User.object.filter(username__startswith="").annotate(max_price=Max("order__price")).values("username","max_price")

            ps:1、在模型类中关联字段设置db_constraint=False,可使约束仅限于orm而不影响到到数据库 

              2、频繁使用多对多会生成大量的关联表。不利于维护。提前构思好结构。                 

              

               

       

      

        

  • 相关阅读:
    简单两步快速实现shiro的配置和使用,包含登录验证、角色验证、权限验证以及shiro登录注销流程(基于spring的方式,使用maven构建)
    使用postgre数据库实现树形结构表的子-父级迭代查询,通过级联菜单简单举例
    关于cas-client单点登录客户端拦截请求和忽略/排除不需要拦截的请求URL的问题(不需要修改任何代码,只需要一个配置)
    javacpp-opencv图像处理系列:国内车辆牌照检测识别系统(万份测试车牌识别准确率99.7%以上,单次平均耗时39ms)
    最全面的Java字节byte操作,处理Java基本数据的转换及进制转换操作工具,流媒体及java底层开发项目常用工具类
    基于java.util.logging实现轻量级日志记录库(增加根据当前类class初始化,修复线程池模型(javaEE)下的堆栈轨迹顺序与当前调用方法不一致问题)
    java原生实现屏幕设备遍历和屏幕采集(捕获)等功能
    用java实现简单快速的webservice客户端/数据采集器(支持soap1.1和soap1.2标准,支持utf-8编码)
    javacpp-opencv图像处理3:使用opencv原生方法遍历摄像头设备及调用(增加实时帧率计算方法)
    mybatis批量增、删、改(更新)操作oracle和mysql批量写法小记
  • 原文地址:https://www.cnblogs.com/cbslock/p/12148708.html
Copyright © 2011-2022 走看看