django 4 ORM框架

本文深入讲解Django ORM框架,包括其基本概念、模型类创建、数据库的增删改查操作及高级查询技巧。

django ORM框架

  1. ORM框架:
      对象关系映射,是一种程序技术,它允许你使用类和对象对数据库进行操作,从而避免使用SQL语句来操作数据库。
      作用:建立模型类和表之间的对应关系,允许我们通过面向对象的方式来操作数据库。根据设计的模型类生成数据库中的表格。通过简单的配置就可以实现数据库的切换。

  2. 数据库的迁移:根据模型类进行表的创建,这个过程叫做数据库的迁移。迁移是Django同步你对模型所做更改(添加字段、删除模型等)到你的数据库模式的方式。

    1. 生成迁移文件:执行python manage.py makemigrations 将应用下的models.py文件生成一个中间文件,并保存在migrations文件夹中。
    2. 执行迁移脚本程序:执行python manage.py migrate 实现迁移。将每个应用下的migrations目录中的中间文件同步灰数据库。
  3. 模型类的创建:

    1. 创建应用:python manage.py startapp 应用名
    2. 在应用下的models.py中编写模型类。
      from django.db import models
      class 模型类名(models.Model):
          字段名 = models.字段类型(字段选型)
      
    3. 迁移同步:python manage.py makemigrations ; python manage.py migrate
  4. 模型类中的内部类Meta类:
    根本意义上是控制表的某些属性。Meta类下有很多内建的类属性,可以对模型类做一些控制。

  5. ORM操作:
    增删改查,核心是模型类.管理器对象。每个继承自models.Model的模型类,都会有一个objects对象被同样继承下来,这个对象叫管理器对象。
    数据库的增删改查可以通过模型的管理器实现:

  6. 创建数据:Django ORM使用一种直观的方式把数据库表中的数据表示成Python对象,创建数据中的每一条记录就是创建一个数据对象。

    1. 方案一:MyModel.objects.create(属性1=值1,属性2=值2,…)
    2. 方案二:创建MyModel实例对象,并调用save()进行保存:obj=MyMoel(属性=值,…) obj.属性=值 obj.save()

  在shell中调试M层的代码的话,首先要做的就是把我们要操作的模型类给引进来,也就是from 应用名.models import 类名

  T层通过视图作为桥梁,拿到m层的数据进行渲染,使用if for等关键字的时候是{% %},记得在最后end,使用视图传过来的参数时用{{ }},V层把M层的数据拿出来,再传给T层去渲染。

  1. 查询:数据库的查询需要使用管理器对象进行,通过MyModel.objects管理器方法调用查询对象。

    1. all方法相当于获取整个表,返回是一个QuerySet对象,可以当做数组来访问(只要是queryset对象,就可以用print(a1.query)来打印出对应的SQL语句)。在模板类中定义一个__str__方法,就可以让QuerySet对象输出的更加友好:

      def __str__(self):
           return '%s-%s-%s-%s'%(self.title,self.price,self.pub,self.market_price)
      
    2. values方法:values(‘列1’,‘列2’…),查询部分列的数据并返回,相当于select 列1,列2 from xxx,返回查询结果容器,容器内存字典,每个字典代表一条数据

    3. values_list方法与values类似,只不过返回的是元组,得用索引进行访问。

    4. order_by(‘列名’)是按照该列进行排序,默认是升序。

  2. 条件查询:

    1. filter(条件)
      语法:MyModel.objects.filter(属性1=值1,属性2=值2),返回包含此条件的全部的数据集,返回值是一个QuerySet对象,内部存放MyModel实例。多个参数时表示的是and查询

    2. exclude(条件)
      语法:MyModel.objects.exclude(属性1=值1,属性2=值2),返回不包含此条件的全部的数据集。

    3. get(条件):也是通过objects对象进行调用,返回的是满足条件的唯一一条数据,该方法只能返回一条数据,查询结果多余一条或者没有数据则抛出异常。

    4. 非等值的查询:使用查询谓词

      __exact表示等值匹配,例如Book.objects.filter(id__exact=1),查找id=1的数据
      
      __contains表示包含指定值的查询,例如Book.objects.filter(title__contains='p'),查找title中包含p的数据
      
      __startwith表示以xxx开始,__endwith表示以xxx结束
      
      __gt表示大于指定值,例如Book.objects.filter(price__gt=50)表示查询price>50的数据
      
      __gte表示大于等于,__lt表示小于,__lte表示小于等于
      
      __in表示查找在指定范围内的数据,例如Author.objects.filter(country__in=['中国','日本','韩国']
      
      __range表示查找在指定区间范围内的数据,例如Author.objects.filter(age__range=(35,50))
      
  3. 更新操作:

    1. 更改单个数据:

      1. 查:通过get()得到要修改的实体对象。(在try中调用objects的get()方法,因为get()方法一旦查询到0个或者多个匹配的结果,get方法就会抛出异常)
      2. 改:通过对象.属性的方式修改数据
      3. 保存:通过对象.save()保存数据
    2. 批量更新数据:

      直接调用QuerySet的update(属性=值)来实现批量修改。例如:

      books = Book.objects.filter(id__gt=2)
      books.update(price = 30)
      
  4. 删除操作:

    1. 删除单个数据:
      1. 查:通过指定的条件利用get()方法获取该数据对象(在try中调用objects的get()方法,因为get()方法一旦查询到0个或者多个匹配的结果,get方法就会抛出异常)
      2. 删除:调用这个数据对象的delete()方法实现删除
    2. 批量删除:
      1. 查找查询结果集中满足条件的全部QuerySet查询集合对象。(拿到满足条件的一组QuerySet)
      2. 调用查询集合对象的delete()方法实现删除。
    3. 伪删除:
        通常不会轻易地在业务中把数据真正的删掉,而是做伪删除,即在表中添加一个布尔型字段is_active,默认是True。执行删除时,就是将欲删除的数据的is_active字段置为False。
        注意:用伪删除时,确保显示数据的地方,均加了is_active=True的过滤查询。
  5. F对象和Q对象:

    1. F对象:一个F对象代表数据库中某条记录的字段的信息。

      1. 作用:通常是对数据库中的字段值在不获取的情况下进行操作以及用于类属性(字段)之间的比较
      2. 语法:
        from django.db.models import F
        F(‘列名’)
      3. 例如:
        1、更新book中所有的零售价涨10元:
        from django.db.models import F
        Book.objects.all().update(market_price = F('market_price')+10)
        2、对数据库的两个字段进行比较,列出哪些书的零售价高于定价
        from django.db.models import F
        Book.objects.filter(market_price__gt=F('price'))
        
    2. Q对象:当在 获取 查询结果集 使用复杂的逻辑或|、逻辑非~等操作时可以借助于Q对象进行操作。

      1. 例如:想找出定价高于30或中国石油大学出版社的全部的书:

        from django.db.models import Q
        Book.objects.filter(Q(price__gt=30)|Q(pub="中国石油大学出版社"))
        
      2. 运算符:& | ~

        Q(条件1|Q(条件2):条件1成立或者条件2成立
        Q(条件1&Q(条件2):条件1和条件2同时成立
        Q(条件1&~Q(条件2):条件1成立并且条件2不成立
        
  6. 聚合查询:

    1. 聚合查询就是对一个数据表中的一个字段的数据进行部分或者全部的统计查询,例如查询bookstore_book数据表中的全部书的平均价格,查询所有书的总个数等。
    2. 分类:整表聚合+分组聚合
    3. 聚合函数:Sum、Avg、Count、Max、Min等。需要先提前导入,例如from django.db.models import Count
    4. 整表聚合:不带分组的聚合查询是指将全部数据进行集中统计查询。
      1. 语法:MyModel.objects.aggregate(结果变量名=聚合函数(‘列’)),返回的结果是结果变量名和值组成的字典,格式为{“结果变量名”:值}
      2. 例如:Book.objects.aggregate(res=Count(‘id’))
    5. 分组聚合:指通过计算查询结果中每一个对象所关联的对象集合,从而得出总计值(也可以是平均值或者总和),即为查询集的每一项生成聚合
      1. 语法:QuerySet.annotate(结果变量名=聚合函数(‘列’)),返回的结果是个QuerySet
      2. 例如:
        #先用查询结果MyModel.objects.values查找查询要分组聚合的列,MyModel.objects.values('列1','列2')
        pub_set = Book.objects.values('pub')
        #然后通过返回结果的QuerySet.annotate(结果变量名=聚合函数('列'))方法分组聚合得到分组结果
        pub_count_set = pub_set.annotate(res = Count('id'))
        #返回的结果是QuerySet,<QuerySet [{'pub': '中国石油大学出版社', 'res': 2}, {'pub': '人民邮电出版社', 'res': 1}, {'pub': '机械工业出版社', 'res': 1}]>
        #因此,可以在此结果的基础上继续筛选,比如SQL语句中的having,也就是filter方法:pub_count_set.filter(res__gt=1)得到总数大于1的。
        
  7. 原生数据库操作:直接使用sql语句和数据库进行交互。(不推荐)

    1. 查询:使用MyModel.objects.raw()进行数据库查询操作。

      1. 语法:MyModel.objects.raw(sql语句,拼接参数),返回值是一个RawQuerySet集合对象(只支持基础操作,比如循环)
      2. 例如:
        books = models.Book.objects.raw('select * from bookstore_book')
        for book in books:print(book)
        

      (可能会造成SQL注入攻击的漏洞,因此更推荐QRM的语法方式,也可以使用拼接参数的方式防御sql注入攻击)
      wrong:s1=Book.objects.raw(‘select * from bookstore_book where id = %s’%(‘1 or 1=1’))
      right:s1=Book.objects.raw(‘select * from bookstore_book where id = %s’,[‘1 or 1=1’])

    2. 完全跨过模型类来操作数据库-查询、更新、删除:

      1. 导入cursor所在的包:from django.db import connection
      2. 用创建的cursor类的构造函数创建cursor对象,再使用cursor对象,为保证在出现异常时能释放cursor资源,通常使用with语句进行创建操作。
        with connection.cursor() as cur:
             cur.execute('要执行的sql语句','拼接参数')
        
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值