Django的ORM操作

ORM模型

一. 数据库
  1. django配置MySQL

    1. 使用mysqlclient[版本mysqlclient 1.3.13以上]
      1. 安装前确认ubuntu是否已安装python3-dev 和 default-libmysqlclient-dev
      2. 使用命令检查是否安装sudo apt list --installed|grep -E 'libmysqlclient-dev|python3-dev’若无命令输出则需要安装
      3. 安装命令:sudo apt-get install python3-dev default-libmysqlclient-dev
      4. 安装mysqlclient: sudo pip install mysqlclient
      5. 如出现如下报错:unable to execute ‘x86_64-linux-gnu-gcc’: No such file or directory 则需在linux终端执行sudo apt-get install gcc
    2. 使用pymysql
      1. 使用pip install pymysql 安装pymysql
    3. 对比:
      • mysqlclient是C扩展类,安装麻烦,运行速度快;
      • pymysql是纯python实现,安装简单,运行速度不及mysqlclient
  2. 创建项目对应的数据库

    • 进入mysql数据库执行:

      • create database 数据库名 default charset utf8 #创建数据库设置默认编码格式为utf8
      • 通常数据库名保持跟项目名一致
    • 在settings.py文件中进行数据库的配置

      • 修改DATABASES 配置项的内容,将sqlite3改为mysql

        DATABASES = {
            'default': {
                'ENGINE': 'django.db.backends.mysql', #指定数据库的存储引擎
                'NAME': 'mysql_demo', #指定要连接的数据库的名称
                'USER': 'root', #指定登陆到数据库的用户名
                'PASSWORD': 'mysql', #数据库登录密码
                'HOST': '127.0.0.1', #连接数据库的IP
                'PORT': '3306', #连接数据库的端口
            }
        }
        
    • ENGINE:常见的引擎还有:

      ‘django.db.backends.mysql’
      ‘django.db.backends.sqllite3’
      ‘django.db.backends.oracle’
      ‘django.db.backends.postgresql’
      
二. 模型类
  • 模型
    • 定义:是一个python类,它是由django.db.models.Model派生出的子类(即它必须继承至django.db.models.Model)
    • 一个模型类代表着数据库的一张数据表
    • 模型类中的每一个类属性都代表着数据库中的一个字段
    • 模型是数据库交互的接口,是表示和操作数据库的方法和方式
三. ORM框架
  • 定义:ORM(object relational mapping) 对象关系映射,它是一种程序技术,允许使用类和对象对数据库进行操作,避免了通过sql语句操作数据库

  • 作用:

    • 建立模型类和表之间的对应关系,允许我们通过面向对象的方式来操作数据库
    • 根据设计的模型类来生成数据库中的表格
    • 通过简单的配置就可进行数据库的切换(切换settings.py文件中配置的数据库名即可)
  • 优点:

    • 只需要面向对象编程,不需要面向数据库编写代码
    • 对数据库的操作都转换成对类属性和方法的操作
    • 不用编写各种数据库的sql语句
    • 实现了数据模型与数据库的解耦,屏蔽了不同数据库操作上的差异
    • 不在关注用的数据库是mysql、oracle…等数据库的内部细节
    • 通过简单的配置就可以轻松更换数据库,而不需要修改代码
  • 缺点:

    • 对于复杂业务,使用成本较高(对于查询很复杂的业务,需要学习如何使用ORM来实现)
    • 根据对象的操作转换成sql语句,根据查询的结果转化成对象,在映射的过程中会有性能损失
  • ORM 映射图
    'ORM 映射图'

  • 模型示例:

    1. 在子应用中的模型类中添加模型类及字段

      from django.db import models
      # Create your models here.
      class Book(models.Model):
          book_name = models.CharField(verbose_name='书名',max_length=50,default='')
          price = models.DecimalField(verbose_name='价格',max_digits=7,decimal_places=2)
      
    2. 数据库迁移

      1. 迁移是django用来同步对模型所做更改(添加字段,删除模型等)到同步到数据库的方式
        1. 生成迁移文件 - 执行python manage.py makemigrations 将应用下的models.py文件生成一个中间文件,并保存在migrations文件夹中
        2. 执行迁移脚本程序 - python manage.py migrate 执行迁移程序实现迁移,将每个应用下的migrations目录中的中间文件同步到数据库
      2. 迁移生成的数据库表名为:应用名_模型类类名
  • 创建模型类流程总结

    1. 创建应用

    2. 在应用下的models.py文件中编写模型类

      from django.db import models
      class ModelName(models.Model):
          FieldName = models.FieldType(field-options) 
          """
          FieldName:字段名,迁移后对应数据表中字段名
          FieldType:字段类型
          field-options:字段选项
          """
      
    3. 迁移同步 makemigrations&migrate
      注意: 任何关于表结构的修改,务必在对应模型类上进行修改; 向模型类中添加字段时需要设置默认值;

  • 字段类型

    字段类型数据库类型作用参数
    BooleanField()tinyint(1)使用True或False来表示值-
    CharField()varchar-max_length:字符最大长度(必填参数)
    DateField()date表示日期auto_now:每次保存对象时, 自动设置该字段为当前时间(True/False); auto_now_add:当对象第一次被创建时自动设置当前时间(True/False); default:设置当前默认时间(取值:字符串格式时间,如’2021-7-1’) * 以上三个参数只能多选一
    DateTimeField()datetime(6)表示日期和时间参数通DateField
    FloatField()double使用小数表示值-
    DecimalField()decimal(x,y)使用小数表示值max_digits:位数总长度, 包括小数点后的位数, 该值必须大于等于decimal_places;decimal_places: 小数点后的数字长度(即小数位数) *以上两个参数必选
    EmailField()varchar表示邮箱-
    IntegerField()int表示整数-
    ImageField()varchar(100)在数据库中为了保存图片的路径-
    TextField()longtext表示不定长的字符数据-

    注:更多字段类型说明参考官方文档

  • 字段选项
    字段选项用于指定创建列的额外的信息;允许出现多个字段选项,多个选项之间用逗号隔开

    字段选项说明
    primary_key如果设置为True,表示该列为主键,如果指定一个字段为主键,则此数据库不会创建id字段
    blank设置为True时,该字段可以为空(在管理后台中编辑数据的时候可以为空),设置为False时,该字段时必须填写的
    null设置为True时,表示该列值允许为空,默认为False,如果此项为False时建议加入default选项来设置默认值
    default设置所在列的默认值,如果字段null=false建议添加此项
    db_index设置为True时,表示为该列增加索引
    unique设置为True时,表示该字段在数据库中的值必须是唯一不能重复出现的
    db_column指定列的名称,如果不指定的话则采用类属性名作为列名
    verbose_name设置此字段在admin界面显示的名称,不设置则默认以类属性名显示

    注:更多字段选项说明参考官方文档

  • 模型类 - Meta类(控制表相关属性)

    • 定义:使用内部Meta类来给模型赋予属性,Meta类下有很多内建的类属性,可对模型类做一些控制

    • 常见Meta类的内建属性:

      属性作用
      db_table=‘数据表名’修改该模型所用的数据表的名称,设置完成后需要立马更新同步数据库
      verbose_name=‘单数名’给模型一个易于理解的名称(单数),用于显示在/admin管理界面中
      verbose_name_plural=‘复数名’该对象复数形式的名称,用于显示在/admin管理界面中
    • 更改当前模型类对应的表名

      #file:models.py
      from django.db import models
      class Books(models.Model):
          class Meta:
              db_table = 'book' #改变当前模型类对应的表名为book
      
    • ORM 基本操作 包括数据库的增删改查(增加:Create、读取:Read、更新:Update、删除:Delete)

    • ORM CRUD核心 -> 模型类.管理器对象

    • 管理器对象: 每个继承自models.Model的模型类,都会有一个objects对象被同样继承下来,这个对象就叫管理器对象

      class MyModel(models.Model):
          ···
      MyModel.objects.create(···) #objects就是管理器对象
      
    • 创建数据 -> 创建数据中每一条记录就是创建一个数据对象

      • 方案一:MyModel.objects.create(属性1=值1,属性2=值2)
        • 成功:返回创建好的数据
        • 失败:抛出异常
      • 方案二:创建MyModel实例对象,并调用save()进行保存
        • obj = MyModel()
        • obj.属性1 = 值1
        • obj.属性2 = 值2
        • obj.save() #执行save()后数据才会提交到数据库中
      • django shell :在django中提供了一个交互式的操作项目交django shell,它能够在交互模式用项目工程的代码执行相应的操作;利用django shell 可以代替编写view的代码来进行直接操作 注意:项目代码发生变化时,需要重新进入django shell; 进入方式: python manage.py shell
    • 查询数据 -> 数据库的查询也需要使用管理器对象进行(可用QuerySet对象.query显示ORM转换为SQL语句的查询方法)

    • 通过MyModel.objects管理器方法调用查询方法

      方法用法作用返回值
      all()MyModel.objects.all()查询MyModel表中的所有数据,等同于select * from tableQuerySet容器对象,内部存放MyModel实例, ]>
      values( ‘列1’, ‘列2’)MyModel.objects.values()查询部分列的数据并返回,等同于select 列1,列2 from tableQuerySet容器对象,内部存放字典, 每个字典代表一条数据;格式为{‘列1’:值1,‘列2’:值2}
      values_list( ‘列1’, ‘列2’)MyModel.objects.values_list()返回元组形式的查询结果,等同于select 列1,列2 from xxxQuerySet容器对象,内部存放元组, 会将查询出来的数据封装到元组中,再封装到查询集合QuerySet中, 如果需要将查询结果取出,需要使用索引的方式取值
      order_by( ‘列1’, ‘列2’)MyModel.objects.order_by()与all()方法不同, 它会用SQL语句的ORDER BY子句对查询结果进行根据某个字段选择性的进行排序, 默认是按照升序排序,降序排序需要在列前面增加‘-’表示QuerySet容器对象,内部存放MyModel实例, 将实例按指定字段进行排序(等同于MyModel.objects.all().order_by(‘列1’))
      filter(条件)MyModel.objects.filter(属性1=值1,属性2=值2) 多个属性在一起时为“与”关系返回包含此条件的全部的数据集QuerySet容器对象,内部存放MyModel实例
      exclude(条件)MyModel.objects.exclude(条件) 多个属性在一起时为“与”关系返回不包含此条件的全部的数据集QuerySet容器对象,内部存放MyModel实例
      get(条件)MyModel.objects.get(条件)返回满足条件的唯一一条数据,查询结果多余一条数据则抛出Model.MultipleObjectsReturned异常,查询结果如果没有数据则抛出Model.DoesNotExist异常QuerySet容器对象,内部存放MyModel实例
    • 查询谓词

      • 定义:做更灵活的条件查询时需要使用查询谓词
      • 说明:每一个查询谓词是一个独立的查询功能
      • 语法:类属性__查询谓词
        查询谓词说明示例
        __exact等值匹配Author.objects.filter(id__exact==1) 等同于select * from author where id = 1
        __contains包含指定值Author.objects.filter(name__contains=‘w’) 等同于select * from author where name like ‘%w%’
        __startwith以xxx开始Author.objects.filter(name__startwith=‘w’) 等同于select * from author where name like ‘w%’
        __endwith以xxx结束Author.objects.filter(name__endwith=‘w’) 等同于select * from author where name like ‘%w’
        __gt大于指定值Author.objects.filter(age__gt=50) 等同于select * from author where age > 50
        __gte大于等于指定值Author.objects.filter(age__gte=50) 等同于select * from author where age >= 50
        __lt小于指定值Author.objects.filter(age__lt=50) 等同于select * from author where age < 50
        __lte小于等于指定值Author.objects.filter(age__lte=50) 等同于select * from author where age <= 50
        __in查找数据是否在指定范围内Author.objects.filter(country__in=[‘中国’,‘日本’,‘韩国’]) 等同于select * from author where country in [‘中国’,‘日本’,‘韩国’]
        __range查找数据是否在指定的区间范围内Author.objects.filter(age__range=(30,50)) 等同于select * from author where author between 35 and 50
        更多查询谓词参考官方文档
  • ORM 更新操作

    • 更新单个数据 - > 修改单个实体的某些字段值的步骤

      1. 查 -> 通过get()得到要修改的实体对象
      2. 改 -> 通过对象.属性 的方式修改数据
      3. 保存 -> 通过对象.save()保存数据
    • 批量更新数据 -> 直接调用QuerySet的update(属性=值)实现批量修改

      #示例
      #将id大于3的所有图书价格定位0元
      books = Book.objects.filter(id__gt==3)
      books.update(price=0)
      
  • ORM 删除操作

    • 单个数据删除 :

      1. 查 -> 查找查询结果对应的一个数据对象

      2. 删 -> 调用这个数据对象的delete()方法实现删除

        try:
            auth = Author.objects.get(id=1)
            auth.delete()
        except:
            print("删除失败")
            ```
        
        
    • 批量数据删除

      1. 查 -> 查找查询结果中满足条件的全部QuerySet查询集合对象

      2. 删 -> 调用查询集合对象的delete()方法实现删除

        #删除年龄≥65的全部信息
        auths = Author.objects.filter(age__gt=65)
        auths.delete()
        
    • 伪删除

      • 通常不会轻易在业务里把数据真正删掉,取而代之的是做伪删除,即在表中添加一个布尔型字段(is_active、is_delete),默认是True;执行删除时,将要删除数据的(is_active、is_delete)字段值设为False
      • 注意:用伪删除时,确保显示数据的地方,均加了is_active/is_delete=True的过滤查询
  • F对象

    • 定义:一个F对象代表数据库中某条记录的字段的信息

    • 作用:

      • 通常是对数据库中的字段值在不获取的情况下进行操作
      • 用于类属性(字段)之间的比较
    • 语法:

      from django.db.models import F
      f('列名')
      
  • Q对象

    • 作用:在条件中用来实现逻辑或 | 、逻辑非~、逻辑与&等操作

    • 语法:

      from django.db.models import Q
      Q(条件1) | Q(条件2) #条件1或者条件2成立
      Q(条件1) & Q(条件2) #条件1和条件2同时成立
      Q(条件1) &~ Q(条件2) #条件1成立且条件2不成立
      

      F对象与Q对象举例见链接

四. F对象和Q对象
  • F对象(标记字段)

    • 定义:一个F对象代表数据库中某条记录的字段的信息

    • 作用:

      • 通常时对数据库中的字段值不获取的情况下进行操作

      • 用于类属性(字段)之间的比较

      • 语法

        from django.db.models import F
        f('列名')
        
    • 示例1:

      #更新Book实例中,将每本书的零售价上涨10元 -- F对象实现
      Book.objects.all().update(market_price=F('market_price') + 10) # market_price += 10
      #等同于sql语句 -> UPDATE 'bookstore_book' SET 'market_price' = ('bookstore_book'.'market_price' + 10)
      
      #更新Book实例中,将每本书的零售价上涨10元 -- 常规操作实现
      books = Book.objects.all()
      for book in books:
          book.market_price = book.market_price + 10 #先将每本书的售价查询出来,再加上10
          book.save()
      
    • 示例2:文章点赞

      # 常规点赞操作
      def add_like(request,topic_id):
          topic = Topic.objects.get(id = topic_id) #查询出点赞的文章
          new_like = topic.like + 1 #取出当前文章的点赞数,并增加1
          """等同于sql语句:update topic set like =1 where id = xxx"""
          topic.like = new_like #将增加后的点赞数复制到字段中
          topic.save() # 保存
      
      #使用F对象实现
      def add_like(request,topic_id):
          topic = Topic.objects.get(id = topic_id) #查询出点赞的文章
          topic.like = F('like') + 1 #等同于 topic.like += 1
          """等同与mysql 语句: update topic set like = like +1 where id = xxx"""
          topic.save()
      

      使用常规方法实现点赞:假设同时有一万条点赞数据进行并行处理,这一万条数据的topic.like查询到的like值都为0,执行new_like = topic.like + 1后like的值都为1,提交到数据库后like的值也是1;
      使用F对象实现点赞操作:利用mysql的innodb引擎的行锁功能,在进行数据的写入更新时,别人是操作不了数据的,间接性的上了一把锁,防止数据库多事物并发的问题。(like = like +1都是在like的基础上like+=1,而不是set like = 1)

    • 示例3:对数据库中两个字段的值进行比较,列出哪些书的零售价高于定价

      #使用F对象实现
      from django.db.models import F
      from bookstore.models import Book
      books = Book.objects.filter(market_price__gt=F('price'))
      """等同于sql语句:SELECT * FROM 'bookstore_book' WHERE 'bookstore_book'.'market_price' > ('bookstore_book'.'price')"""
      for book in books:
          print(book.title,'定价:',book.price,'现价:',book.market_price)
      
  • Q对象(或与非)

    • 作用:在条件中用来实现逻辑或 | 、逻辑非~、逻辑与&等操作

    • 语法:

      from django.db.models import Q
      Q(条件1) | Q(条件2) #条件1或者条件2成立
      Q(条件1) & Q(条件2) #条件1和条件2同时成立
      Q(条件1) &~ Q(条件2) #条件1成立且条件2不成立
      
    • 示例1:

      #过滤出定价低于20元或者清华大学出版社出版的全部书籍
      Book.objects.filter(Q(price__lt=20) | Q(pub='清华大学出版社'))
      
  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值