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、频繁使用多对多会生成大量的关联表。不利于维护。提前构思好结构。                 

          

           

   

  

    

猜你喜欢

转载自www.cnblogs.com/cbslock/p/12148708.html