[Python] Django ORM与执行原生SQL实现操作数据库

news2025/7/28 0:45:53

前言

系列文章目录
[Python]目录


文章目录

  • 前言
  • 🍉 ORM
  • 🍉 shell
  • 🍉 模型类与数据的准备
    • 🍒 模型类
    • 🍒 数据
  • 🍉 查询数据
    • 🍒 查询集
      • 🍓 查询集的特性
        • 🍎 惰性执行
        • 🍎 缓存
    • 🍒 简单查询
      • 🍓 all():查询模型对应数据表中所有数据
      • 🍓 get():查询数据表中满足指定条件的数据
      • 🍓 values():获取需要的字段
      • 🍓 distinct():对查询出来的数据记录进行去重
      • 🍓 count():统计查询结果中数据记录的数量
    • 🍒 过滤查询 filter() & get() & exclude()
      • 🍓 语法
      • 🍓 运算符
      • 🍓 相等
      • 🍓 模糊查询
      • 🍓 空查询
      • 🍓 范围查询
      • 🍓 比较查询
      • 🍓 日期查询
    • 🍒 F对象(两个属性进行比较)
      • 🍓 语法
    • 🍒 Q对象(逻辑或与非查询)
      • 🍓 语法
      • 🍓 逻辑与查询
      • 🍓 逻辑或查询
      • 🍓 逻辑非查询
    • 🍒 聚合函数
    • 🍒 排序
    • 🍒 关联查询
      • 🍓 由一到多的访问
      • 🍓 由多到一的访问
      • 🍓 由一到一的访问
      • 🍓 由多到多的访问
      • 🍓 select_related()
      • 🍓 prefetch_related()
      • 🍓 关联查询的筛选
  • 🍉 新增数据
    • 🍒 方式一:实例化模型类,save()保存新增数据
    • 🍒 方式二:直接create()新增数据入库
  • 🍉 更新数据
    • 🍒 方法一:获取模型对象修改对象属性,save()保存修改数据
    • 🍒 方法二:直接update()修改数据
    • 🍒 objects调用update()批量更新所有数据
    • 🍒 批量更新多行数据
  • 🍉 删除数据
    • 🍒 方法一:获取指定数据对象调用delete()删除该数据对象
    • 🍒 方法二:过滤出指定数据对象调用delete()删除过滤出来的数据对象
    • 🍒 删除多行数据
    • 🍒 删除全部数据
  • 🍉 执行原生SQL
    • 🍒 raw()
    • 🍒 游标
      • 🍓 用法
      • 🍓 插入数据
      • 🍓 查询数据
      • 🍓 更新数据
      • 🍓 删除数据
  • 🍉 事务处理
    • 🍒 装饰器方式
    • 🍒 with 语句方式


🍉 ORM

在Django MVT设计模式中的Model,专门负责和数据库进行交互,对应的文件 models.py。Model中内嵌了ORM框架,使得我们不需要直接面向数据库编程,而是定义模型类,通过模型类和对象完成数据库表的增删改查。

ORM框架就是把数据库表中的行与相应模型类的对象相对应,把数据库中的表与模型类相对应,把数据库中表的字段与模型类的属性相对应。

在这里插入图片描述

使用ORM框架操作数据库,我们可以不用关心底层具体使用的是哪个数据库,只需要关心ORM框架即可。如果需要使用不同的数据库,我们只需要在Django框架中进行相应的配置,ORM会自动连接对应的数据库,如果需要对数据库进行增删改查,我们也只需要操作ORM即可,ORM会自动生成对应的数据库的sql语言。

在这里插入图片描述

🍉 shell

Django的manage工具提供了shell命令,以便我们可以直接在终端中执行测试python语句。

Django manage提供的shell类似于ipython;
使用shell工具,可以帮助我们更好的测试代码,对于有关模型的代码(数据对象的增删改查)可以使用shell进行测试,就不用书写路由和请求响应到浏览器客户端进行查看。

启动shell,在命令窗口运行:

python manage.py shell

在这里插入图片描述

测试,导入两个模型类,并查询两个模型类对应的所有数据对象:

# 导入两个模型类
from book.models import BookInfo,PeopleInfo
# 查询两个模型类对应的所有数据对象
BookInfo.objects.all()
PeopleInfo.objects.all()

在这里插入图片描述

有关模型类的代码写在models.py中,对数据进行增删改查的代码书写在views.py中,对数据进行增删改查需要实例化模型类,在views.py中导入模型类,对数据进行增删改查。

🍉 模型类与数据的准备

🍒 模型类

from django.db import models


# Create your models here.
class BookInfo(models.Model):
    name = models.CharField(max_length=10, unique=True, verbose_name='书籍名')
    pub_date = models.DateField(null=True)  # 发布日期
    read_count = models.IntegerField(default=0)  # 阅读数
    comment_count = models.IntegerField(default=0)  # 评论数
    is_delete = models.BooleanField(default=False)  # 是否被逻辑删除

    class Meta:
        db_table = 'bookinfo'  # 指定模型对应数据库中表的表名
        verbose_name = '书籍信息'  # 修改后台admin显示的表名

    def __str__(self):
        return self.name


# 准备人物列表信息的模型类
class PeopleInfo(models.Model):
	# 性别的可选值 0对应male 1对应female
    GENDER_CHOICES = (
        (0, 'male'),
        (1, 'female')
    )
    name = models.CharField(max_length=20, verbose_name='名称')  # 人物的名字
    gender = models.SmallIntegerField(choices=GENDER_CHOICES, default=0, verbose_name='性别')  # 人物的性别
    description = models.CharField(max_length=200, null=True, verbose_name='描述信息')  # 人物的描述信息
    book = models.ForeignKey(BookInfo, on_delete=models.CASCADE, verbose_name='图书')  # 引用外键,引用的模型为BookInfo
    is_delete = models.BooleanField(default=False, verbose_name='逻辑删除')  # 是否被逻辑删除

    class Meta:
        db_table = 'peopleinfo'
        verbose_name = '人物信息'

    def __str__(self):
        return self.name

🍒 数据

表 bookinfo:

insert into bookinfo(name, pub_date, read_count,comment_count, is_delete) values
('射雕英雄传', '1980-5-1', 12, 34, 0),
('天龙八部', '1986-7-24', 36, 40, 0),
('笑傲江湖', '1995-12-24', 20, 80, 0),
('雪山飞狐', '1987-11-11', 58, 24, 0);

在这里插入图片描述

表 peopleinfo:

insert into peopleinfo(name, gender, book_id, description, is_delete)  values
    ('郭靖', 1, 1, '降龙十八掌', 0),
    ('黄蓉', 0, 1, '打狗棍法', 0),
    ('黄药师', 1, 1, '弹指神通', 0),
    ('欧阳锋', 1, 1, '蛤蟆功', 0),
    ('梅超风', 0, 1, '九阴白骨爪', 0),
    ('乔峰', 1, 2, '降龙十八掌', 0),
    ('段誉', 1, 2, '六脉神剑', 0),
    ('虚竹', 1, 2, '天山六阳掌', 0),
    ('王语嫣', 0, 2, '神仙姐姐', 0),
    ('令狐冲', 1, 3, '独孤九剑', 0),
    ('任盈盈', 0, 3, '弹琴', 0),
    ('岳不群', 1, 3, '华山剑法', 0),
    ('东方不败', 0, 3, '葵花宝典', 0),
    ('胡斐', 1, 4, '胡家刀法', 0),
    ('苗若兰', 0, 4, '黄衣', 0),
    ('程灵素', 0, 4, '医术', 0),
    ('袁紫衣', 0, 4, '六合拳', 0);

在这里插入图片描述

🍉 查询数据

🍒 查询集

查询集,也称查询结果集(QuerySet),表示从数据库中获取的对象集合,查询集不是简单的列表。

当调用如下方法时,Django会返回查询集:
1.all()
2.filter()
3.exclude()
4.values()
5.distinct()

🍓 查询集的特性

🍎 惰性执行

创建的查询集不会立即访问数据库将数据查询出来,直到调用查询数据的时候,才会访问数据库将数据库中满足条件的数据查询出来。

🍎 缓存

如果多次数据查询使用的是同一个查询集,则只有第一次使用时会发生数据库的查询,然后Django会把结果缓存下来,再次使用这个查询集时会使用缓存的数据,减少了数据库的查询次数。如果多个查询集无法重用缓存,则每次查询都会与数据库进行一次交互,增加了数据库的负载。经过存储后,可以重用查询集,第一次查询后的查询可以直接使用缓存中的数据,减少了数据库的查询次数。

🍒 简单查询

对数据进行增删改查都可以通过调用模型类的模型管理类对象objects来实现

🍓 all():查询模型对应数据表中所有数据

all()方法可以一次性查询出模型对应的数据表中所有的数据,且该方法返回的结果为QuerySet对象。

all()方法返回的QuerySet对象是一个由数据表中所有数据记录组成的列表。

🌰 1.导入模型类:

from subapp01.models import BookInfo  # 导入模型

🌰 2.通过objects调用all()方法获取BookInfo模型对应数据表中的所有数据

books = BookInfo.objects.all()

在这里插入图片描述

🍓 get():查询数据表中满足指定条件的数据

注意,get()方法只能用于查询查询结果唯一的情况,get()方法只能用于查询返回符合要求只有一条数据的情况,当查询结果中没有记录或者记录超过一条时都会报错抛出异常。

🌰 1.导入模型类:

from subapp01.models import BookInfo  # 导入模型

🌰 2.通过objects调用get()方法获取BookInfo模型对应数据表中符合条件的数据记录

book = BookInfo.objects.get(id=8)
>>> from subapp01.models import BookInfo
>>> book = BookInfo.objects.get(id=8)    
>>> book                                 
<BookInfo: 射雕英雄传>
>>> book.name
'射雕英雄传'
>>> book.read_count
12
>>>

🍓 values():获取需要的字段

values()方法可以用于获取需要的字段,该方法返回的为一个QuerySet对象,该对象包含的数据类型为由指定的字段和值形成的字典。

values()方法返回的QuerySet对象是一个由数据记录字段和值组成的字典形成的列表。

🌰 1.导入模型类:

from subapp01.models import BookInfo  # 导入模型

🌰 2.调用values()方法获取BookInfo模型对应数据表中数据记录的指定字段

# 查询出所有数据记录后筛选出数据记录的id、name、read_count字段
books = BookInfo.objects.all().values('id', 'name', 'read_count')
>>> from subapp01.models import BookInfo  # 导入模型
>>> books = BookInfo.objects.all().values('id', 'name', 'read_count')
>>> books
<QuerySet [{'id': 8, 'name': '射雕英雄传', 'read_count': 12}, {'id': 9, 'name': '天龙八部', 'read_count': 36}, {'id': 10, 'name': '笑傲江湖', 'read_count': 20}, {'id': 11, 'name': '雪山飞狐', 'read_count': 58}]>
>>> books[0] 
{'id': 8, 'name': '射雕英雄传', 'read_count': 12}
>>> books[0]['name']
'射雕英雄传'
>>>

🍓 distinct():对查询出来的数据记录进行去重

该方法用于去除重复数据,返回的为一个QuerySet对象,该对象中包含的数据为去重之后的数据。

🌰 1.导入模型类:

from subapp01.models import BookInfo  # 导入模型

🌰 2.调用distinct()方法对查询出来的数据记录进行去重

data = BookInfo.objects.all().values('is_delete').distinct()

在这里插入图片描述

>>> from subapp01.models import BookInfo  # 导入模型
>>> data = BookInfo.objects.all().values('is_delete').distinct()
>>> data
<QuerySet [{'is_delete': False}]>
>>> 

🍓 count():统计查询结果中数据记录的数量

该方法返回查询结果中数据记录的数量。

🌰 1.导入模型类:

from subapp01.models import BookInfo  # 导入模型

🌰 2.调用count()方法对查询出来的数据记录进行数量的统计

count = BookInfo.objects.all().count()
>>> from subapp01.models import BookInfo
>>> count = BookInfo.objects.all().count()
>>> count
4
>>>

🍒 过滤查询 filter() & get() & exclude()

使用filter()、get()、exclude()进行过滤查询相当于SQL中的where语句select * from 表 where 条件语句

filter():筛选符合条件的n个结果(n的取值为0-n)。返回结果为一个QuerySet对象,该对象是一个由数据记录组成的列表。

get():筛选符合条件的1个结果(返回结果只能一个,大于一个会报错),返回一个数据记录对象

exclude():排除掉符合条件之后剩下的数据组成的结果集,该结果集是一个QuerySet对象,该对象是一个由数据记录组成的列表,相当于条件语句中not。

🍓 语法

以filter()为例

filter(字段名__运算符=)

字段名和运算符间使用两个下划线进行分割,所以属性名不能包括多个下划线。

🍓 运算符

  • 相等
    • exact:表示判等。
  • 模糊查询
    • contains:是否包含。
      • 说明:如果要包含%无需转义,直接写即可。
    • startswith、endswith:以指定值开头或结尾。
    • 以上运算符都区分大小写,在这些运算符前加上i表示不区分大小写,如iexact、icontains、istartswith、iendswith.
  • 空查询
    • isnull:是否为null。
  • 范围查询
    • in:是否包含在范围内。
  • 比较查询
    • gt大于 (greater then)
    • gte大于等于 (greater then equal)
    • lt小于 (less then)
    • lte小于等于 (less then equal)
    • 不等于的运算符,使用exclude()过滤器。
  • 日期查询
    • year、month、day、week_day、hour、minute、second:对日期时间类型的属性进行运算。

🍓 相等

exact:表示判等。

# 查询编号为1的图书
# exact相当于 等于号
book = BookInfo.objects.get(id__exact=1)
# 简写形式
book = BookInfo.objects.get(id=1)

在这里插入图片描述

# exact相当于 等于号
book = BookInfo.objects.filter(id__exact=1)
# 简写形式
book = BookInfo.objects.filter(id=1)

返回结果为一个QuerySet对象,该对象是一个由数据记录组成的列表。

在这里插入图片描述

🍓 模糊查询

  • contains:是否包含。
    • 说明:如果要查询数据中是否包含%,无需转义,直接写%即可。
  • startswith、endswith:以指定值开头或结尾。
  • 以上运算符都区分大小写,在这些运算符前加上i表示不区分大小写,如iexact、icontains、istartswith、iendswith.
# 查询书名包含'湖'的图书
# 不知道返回结果有几个,使用filter
# 包含 运算符 contains
# 如果要包含%无需转义,直接写即可
books = BookInfo.objects.filter(name__contains='湖')

在这里插入图片描述

# 查询书名以'部'结尾的图书
# 不知道返回结果有几个,使用filter
# startswith、endswith:以指定值开头或结尾。
books = BookInfo.objects.filter(name__endswith='部')

在这里插入图片描述

🍓 空查询

isnull:是否为null。

# 查询书名为空的图书
books = BookInfo.objects.filter(name__isnull=True)

在这里插入图片描述

🍓 范围查询

in:是否包含在范围内。

# 查询编号为1或3或5的图书
books = BookInfo.objects.filter(id__in=[1, 3, 5])

在这里插入图片描述

🍓 比较查询

  • gt大于 (greater then)
  • gte大于等于 (greater then equal)
  • lt小于 (less then)
  • lte小于等于 (less then equal)
  • 不等于的运算符,使用exclude()过滤器。
# 查询编号大于3的图书
books = BookInfo.objects.filter(id__gt=3)

在这里插入图片描述

# 查询编号不大于3的图书
books = BookInfo.objects.exclude(id__gt=3)

在这里插入图片描述

🍓 日期查询

year、month、day、week_day、hour、minute、second:对日期时间类型的属性进行运算。

# 查询1980年发表的图书
books = BookInfo.objects.filter(pub_date__year='1980')

在这里插入图片描述

# 查询1990年1月1日后发表的图书
books = BookInfo.objects.filter(pub_date__gt='1990-1-1')

这里是引用

注意:
日期的格式只能YYYY-MM-DD
在这里插入图片描述
在这里插入图片描述

🍒 F对象(两个属性进行比较)

之前的查询都是对象的属性与常量值比较,如果需要两个属性之间进行比较,则使用F对象,F对象被定义在django.db.models中。

🍓 语法

以filter为例

filter(字段名__运算符=F('字段名'))
from django.db.models import F


# 查询阅读量大于等于评论量的图书。
books = BookInfo.objects.filter(read_count__gt=F('comment_count'))

在这里插入图片描述
在这里插入图片描述

# 查询阅读量大于2倍评论量的图书。
books = BookInfo.objects.filter(read_count__gt=F('comment_count') * 2)

在这里插入图片描述

🍒 Q对象(逻辑或与非查询)

如果需要实现逻辑或or、逻辑与and、逻辑非not的查询,则可以使用Q()对象结合|&~运算符进行数据的查询,Q对象被义在django.db.models中。

🍓 语法

# 以逻辑或查询为例
Q(属性名__运算符=)|Q(属性名__运算符=)|Q(属性名__运算符=)|···

🍓 逻辑与查询

Q对象可以使用&连接,&表示逻辑与。

from django.db.models import Q


# 查询阅读量大于20,并且编号小于3的图书。
# 方法一: 进行多次过滤得到结果
books = BookInfo.objects.filter(read_count__gt=20).filter(id__lt=3)
# 方法二:
books = BookInfo.objects.filter(read_count__gt=20, id__lt=3)
# 方法三:使用Q对象相与
books = BookInfo.objects.filter(Q(read_count__gt=20) & Q(id__lt=3))

在这里插入图片描述

🍓 逻辑或查询

逻辑或查询只能使用Q对象实现

Q对象可以使用|连接,|表示逻辑或。

# 查询阅读量大于20,或编号小于3的图书
books = BookInfo.objects.filter(Q(read_count__gt=20) | Q(id__lt=3))

在这里插入图片描述

🍓 逻辑非查询

Q对象前可以使用~操作符,表示逻辑非 not。

# 查询编号不等于3的图书。
books = BookInfo.objects.exclude(id=3)

books = BookInfo.objects.filter(~Q(id=3))

在这里插入图片描述

🍒 聚合函数

在查询数据时需要使用聚合函数,则需要使用aggregate()过滤器调用聚合函数来进行数据的查询。

聚合函数包括:Avg平均,Count数量,Max最大,Min最小,Sum求和,被定义在django.db.models中。

语法:

aggregate(聚合函数('字段名'))

注意aggregate的返回值是一个字典类型,格式如下:
{'属性名__聚合类小写':值}

# 导入聚合函数
from django.db.models import Avg, Count, Max, Min, Sum

# 查询图书的总阅读量。
books = BookInfo.objects.aggregate(Sum('read_count'))

在这里插入图片描述

🍒 排序

使用order_by()对结果进行排序.

降序排序只需要在指定字段前加一个负号即可

# 根据评论数对所有图书的查询结果进行排序
# 默认升序
books = BookInfo.objects.all().order_by('comment_count')
# 降序
books = BookInfo.objects.all().order_by('-comment_count')

在这里插入图片描述

# 根据阅读数和id对所有图书的查询结果进行排序
# 阅读数升序,相同时按照id号升序排序
books = BookInfo.objects.all().order_by('read_count', 'id')
# 阅读数升序,相同时按照id号降序排序
books = BookInfo.objects.all().order_by('read_count', '-id')

在这里插入图片描述

在这里插入图片描述

🍒 关联查询

🍓 由一到多的访问

已知主表(被从表建立外键引用)数据,关联查询从表(引用主表)数据。

语法:

当在两个模型中使用外键建立关联之后,Django会在被从表关联的主表模型中自动生成添加可以用于进行反向操作(因为外键在从表,主表连接从表查询数据为反向操作)的属性 从表模型类名小写,如果在从表定义外键时有指定反向操作时使用的名称,则使用指定的名称进行反向操作。

主表模型(或实例对象).从表模型类名小写_set
# 查询书籍为1的所有人物信息
# 1. 查询id为1的书籍
book = BookInfo.objects.get(id=1)
# 2. 根据书籍关联任务信息
people = book.peopleinfo_set.all()

在这里插入图片描述

在这里插入图片描述

🍓 由多到一的访问

已知从表数据,关联查询主表数据。

语法:

从表模型(或实例对象).从表模型中的外键属性
from book.models import PeopleInfo


# 查询人物为1的书籍信息
# 1. 查询id为1的人物信息
person = PeopleInfo.objects.get(id=1)
# 2. 根据人物信息获取人物对应的书籍信息
book = person.book

在这里插入图片描述

在这里插入图片描述

🍓 由一到一的访问

一到一的访问为上述一到多和多到一的特例,在进行主表关联从表和从表关联主表的查询时,依旧可以使用上述的方法进行数据的关联查询。有定义外键的模型使用外键进行关联,没有定义外键的模型(被关联的模型)使用Django在被关联的模型中自动生成添加用于进行反向操作的属性 关联模型类名小写 进行关联查询。

🍓 由多到多的访问

与上述一到多和多到一的查询方法类似,有定义外键的模型使用外键进行关联,没有定义外键的模型(被关联的模型)使用Django在被关联的模型中自动生成添加用于进行反向操作的属性 关联模型类名小写 进行关联查询。

🍓 select_related()

可以将关联的模型数据提取出来,可以减少数据库查询的次数。

用于一到多的关联查询

主表模型.objects.select_related("关联从表模型名小写")

🍓 prefetch_related()

可以将关联的模型数据提取出来,可以减少数据库查询的次数。

用于多到一和多到多的关联查询

从表模型.objects.prefetch_related("关联主表模型名小写")

🍓 关联查询的筛选

Django会在被关联的模型中自动生成添加可以用于进行反向操作的属性 关联模型类名小写

# 查询图书,要求图书人物为“郭靖”
# 需要查询的为书籍信息,已知条件为人物信息
# 需要查询的为主表信息,已知条件为从表(外键定义所在的模型对应的表)信息
# 语法:
# filter(关联从表模型类名小写__字段名__运算符=值)
book = BookInfo.objects.filter(peopleinfo__name__exact='郭靖')
# 简写
book = BookInfo.objects.filter(peopleinfo__name='郭靖')

在这里插入图片描述

# 查询图书,要求图书中人物的描述包含"八"
book = BookInfo.objects.filter(peopleinfo__description__contains='

在这里插入图片描述

从表模型中有一个外键属性

# 需要查询的为人物信息,已知条件为书籍信息
# 需要查询的为从表信息,已知条件为主表信息
# 语法:
# filter(外键名__字段名__运算符=值)
# 查询书名为“天龙八部”的所有人物
people = PeopleInfo.objects.filter(book__name__exact='天龙八部')
# 简写
people = PeopleInfo.objects.filter(book__name='天龙八部')
# 查询图书阅读量大于30的所有人物
people = PeopleInfo.objects.filter(book__read_count__gt=30)

在这里插入图片描述

🍉 新增数据

🍒 方式一:实例化模型类,save()保存新增数据

🌰 1.导入模型类:

from subapp01.models import BookInfo  # 导入模型

🌰 2.实例化模型对象

写法1:实例化模型类型对象,并且在实例化的时候为属性赋值,会返回对应的新数据对象

book = BookInfo(
    name='python',
    pub_date='2000-01-01'
    # 其他属性有默认值,这边就不进行赋值了
)

写法2:实例化模型类对象后,单独为实例化后的模型对象的属性赋值

book = BookInfo()
book.name = 'Java'
book.pub_date = '2001-01-01'
# 其他属性有默认值,这边就不进行赋值了

🌰 3.调用save()方法,将新增的数据对象同步到数据库中

book.save()

在这里插入图片描述

🍒 方式二:直接create()新增数据入库

对数据进行增删改查都可以通过调用模型类的模型管理类对象objects来实现

🌰 1.导入模型类:

from subapp01.models import BookInfo  # 导入模型

🌰 2.调用objects的create()方法直接新增数据对象入库

objects的create()方法会把新增的数据对象返回给我们

BookInfo.objects.create(
    name='css3',
    pub_date='2010-01-01'
    # 其他属性有默认值,这边就不进行赋值了
)

在这里插入图片描述
在这里插入图片描述

🍉 更新数据

对数据进行增删改查都可以通过调用模型类的模型管理类对象objects来实现

🍒 方法一:获取模型对象修改对象属性,save()保存修改数据

🌰 1.导入模型类:

from subapp01.models import BookInfo  # 导入模型

🌰 2.获取模型对象

# 查询(获取)出需要进行修改的数据对象  获取id=1的数据对象
book = BookInfo.objects.get(id=1)

🌰 3.修改获取到的实例对象的属性

book.read_count = 2000

🌰 4.调用save()方法将修改后的数据同步数据库

book.save()

在这里插入图片描述

🍒 方法二:直接update()修改数据

🌰 1.导入模型类:

from subapp01.models import BookInfo  # 导入模型

🌰 2.获取模型对象时链式调用update()方法修改对象属性同时将修改后的数据同步到数据库

# 先过滤(filter)出需要进行修改的数据对象,然后修改对象属性
# 此方法会返回受影响的行数
BookInfo.objects.filter(id=1).update(
    read_count = 100,
    comment_count = 2000
)

在这里插入图片描述在这里插入图片描述

get()方法得到的是一个模型对象,模型对象上不具有update()方法,所以不能使用get()方法得到模型对象后直接链式调用update()方法更新数据;而filter()方法返回的是一个QuerySet对象,QuerySet对象上具有update()方法,可以直接链式调用update()方法更新数据。

🍒 objects调用update()批量更新所有数据

🌰 1.导入模型类:

from subapp01.models import BookInfo  # 导入模型

🌰 2.使用objects直接调用update()批量更新所有数据对象(行)数据

该方法会返回数据库中受影响的行数

# 将所有数据对象(行)的read_count修改为500
books = BookInfo.objects.update(read_count=500)

在这里插入图片描述
在这里插入图片描述

🍒 批量更新多行数据

🌰 1.导入模型类:

from subapp01.models import BookInfo  # 导入模型

🌰 2.通过filter()方法过滤出多行数据,然后链式调用update()方法对过滤出来的多行数据对象进行批量更新

该方法会返回受影响的行数

books = BookInfo.objects.filter(read_count=1000).update(read_count=700)

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

🍉 删除数据

🍒 方法一:获取指定数据对象调用delete()删除该数据对象

🌰 1.导入模型类:

from subapp01.models import BookInfo  # 导入模型

🌰 2.获取指定的模型数据对象

book = BookInfo.objects.get(id=5)

🌰 3.获取到的模型数据对象调用delete()方法将自己删除

该方法会返回一个元组类型的数据,元组的第一个元素为本次操作删除的所有表的总行数之和,元组的第二个元素为字典类型,字典中为每个表在本次操作分别删除了几行数据

book.delete()

在这里插入图片描述
在这里插入图片描述

🍒 方法二:过滤出指定数据对象调用delete()删除过滤出来的数据对象

🌰 1.导入模型类:

from subapp01.models import BookInfo  # 导入模型

🌰 2.过滤出指定数据对象直接链式调用delete()方法删除过滤出来的数据对象

该方法会返回一个元组类型的数据,元组的第一个元素为本次操作删除的所有表的总行数之和,元组的第二个元素为字典类型,字典中为每个表在本次操作分别删除了几行数据

book = BookInfo.objects.filter(id=6).delete()

在这里插入图片描述
在这里插入图片描述

🍒 删除多行数据

🌰 1.导入模型类:

from subapp01.models import BookInfo  # 导入模型

🌰 2.过滤出指定数据对象直接链式调用delete()方法删除过滤出来的数据对象

该方法会返回一个元组类型的数据,元组的第一个元素为本次操作删除的所有表的总行数之和,元组的第二个元素为字典类型,字典中为每个表在本次操作分别删除了几行数据

books = BookInfo.objects.filter(read_count=700).delete()

在这里插入图片描述
在这里插入图片描述

🍒 删除全部数据

🌰 1.导入模型类:

from subapp01.models import BookInfo  # 导入模型

🌰 2.使用objects调用all()方法查询出全部数据,然后调用delete()方法删除模型对应的表的全部数据对象

该方法会返回一个元组类型的数据,元组的第一个元素为本次操作删除的所有表的总行数之和,元组的第二个元素为字典类型,字典中为每个表在本次操作分别删除了几行数据

books = BookInfo.objects.all().delete()

在这里插入图片描述

🍉 执行原生SQL

当ORM提供的API无法实现数据的查询时,需要使用原生的SQL语句进行数据的查询,此时我们可以通过执行原生SQL实现数据的查询。

🍒 raw()

在Django中执行原生的SQL语句,我们需要使用raw()方法,raw()方法被定义在django.db.models.Manager模块中。raw()方法返回的结果为RawQuerySet对象,对于RawQuerySet对象可以使用列表下标的方式获取其中的数据对象。

语法:

sql = ''  # sql语句中使用 %s 作为占位符(防止SQL注入)

# 调用row()方法执行原生sql查询数据
模型类.objects.raw(sql, [填充sql中占位符的数据])  # 第二个参数可以使用列表

🌰

from subapp01.models import BookInfo


sql = """
select id, name 
from bookinfo
where id = %s or read_count<=%s;
"""
books = BookInfo.objects.raw(sql, [1, 20])

在这里插入图片描述

>>> from subapp01.models import BookInfo
>>> sql = """
... select id, name
... from bookinfo
... where id = %s or read_count<=%s;
... """
>>> books = BookInfo.objects.raw(sql, [1, 20])
>>> books
<RawQuerySet:
select id, name
from bookinfo
where id = 1 or read_count<=20;
>
# 返回的结果集可以使用列表下标的方式获取数据对象
>>> books[0]
<BookInfo: 射雕英雄传>
>>> books[1]
<BookInfo: 笑傲江湖>
>>>

🍒 游标

在Django中,django.db.connection中封装了数据库的连接对象,我们可以通过数据库的连接对象获取游标,然后通过获取的游标来执行原生SQL语句实现对数据库的增删改查。

🍓 用法

获取数据库的连接对象:

from django.db import connection

通过数据库的连接对象获取游标:

cursor = connection.cursor()

使用游标执行原生sql语句:

cursor.execute(sql, [填充占位符的数据])

关闭游标:

cursor.close()

🍓 插入数据

from django.db import connection


cursor = connection.cursor()
sql = """
insert into bookinfo(name, pub_date)
values (%s, %s);
"""
res = cursor.execute(sql, ('Java', '2020-11-11'))
cursor.close()
>>> from django.db import connection
>>> cursor = connection.cursor()
>>> sql = """
... insert into bookinfo(name, pub_date, read_count, comment_count, is_delete)
... values (%s, %s, %s, %s, %s);
... """
>>> res = cursor.execute(sql, ('Java', '2020-11-11', 100, 50, 0))
>>> res
<django.db.backends.sqlite3.base.SQLiteCursorWrapper object at 0x000002721C9BB0A0>
>>> cursor.close()

在这里插入图片描述

🍓 查询数据

游标对象提供了fetchall()方法用于获取执行sql语句后的全部数据,返回的结果为所有数据对象各字段数据组成的元组形成的列表;以及fetchone()方法用于获取其中的一个结果,第一次执行获取第一条数据记录,此后每执行一次都会返回下一条数据记录,直到所有的数据记录都获取过为止,每次返回的结果为数据对象各字段数据组成的元组。

from django.db import connection


sql = "select * from bookinfo;"
cursor = connection.cursor()
res = cursor.execute(sql)
data = res.fetchall()
cursor.close()
>>> from django.db import connection
>>> sql = "select * from bookinfo;"
>>> cursor = connection.cursor()
>>> res = cursor.execute(sql)
>>> res.fetchall()
[(8, '射雕英雄传', datetime.date(1980, 5, 1), 12, 34, False), (9, '天龙八部', datetime.date(1986, 7, 24), 36, 40, False), (10, '笑傲江湖', datetime.date(1995, 12, 24), 20, 80, False), (11, '雪山飞狐', datetime.d
ate(1987, 11, 11), 58, 24, False), (12, 'Java', datetime.date(2020, 11, 11), 100, 50, False)]
>>> cursor.close()
>>> from django.db import connection
>>> sql = "select * from bookinfo;"
>>> cursor = connection.cursor()
>>> res = cursor.execute(sql)
>>> res.fetchone()
(8, '射雕英雄传', datetime.date(1980, 5, 1), 12, 34, False)
>>> res.fetchone()
(9, '天龙八部', datetime.date(1986, 7, 24), 36, 40, False)
>>> res.fetchone()
(10, '笑傲江湖', datetime.date(1995, 12, 24), 20, 80, False)
>>> res.fetchone()
(11, '雪山飞狐', datetime.date(1987, 11, 11), 58, 24, False)
>>> res.fetchone()
(12, 'Java', datetime.date(2020, 11, 11), 100, 50, False)
>>> res.fetchone()  # 此时以及获取完返回的全部数据记录,所以没有结果输出
>>> cursor.close()

🍓 更新数据

from django.db import connection


sql = "update bookinfo set name='python' where id=%s;"
cursor = connection.cursor()
res = cursor.execute(sql, [12])
res.rowcount  # 获取本次操作在数据库中影响的行数
cursor.close()
>>> from django.db import connection
>>> sql = "update bookinfo set name='python' where id=%s;"
>>> cursor = connection.cursor()
>>> res = cursor.execute(sql, [12])
>>> res.rowcount                                    
1
>>> cursor.close()

在这里插入图片描述

🍓 删除数据

from django.db import connection


sql = "delete from bookinfo where id=%s;"
cursor = connection.cursor()
res = cursor.execute(sql, [12])
res.rowcount  # 获取本次操作在数据库中影响的行数
cursor.close()
>>> from django.db import connection
>>> sql = "delete from bookinfo where id=%s;"
>>> cursor = connection.cursor()
>>> res = cursor.execute(sql, [12])
>>> res.rowcount  # 获取本次操作在数据库中影响的行数
1
>>> cursor.close()

在这里插入图片描述

🍉 事务处理

在Django中,提供了django.db.transaction模块用于事务的处理。

🍒 装饰器方式

from django.db import transaction


@transaction.atomic  # 装饰器
def fun(request):
    save_id = transaction.savepoint()  # 开启事务
    try:
        # 操作1
        # 操作2
        # ......
        transaction.savepoint_commit(save_id)  # 没有出现错误,提交从保存点到当前位置的所有操作
    except:
        transaction.savepoint_rollback(save_id)  # 如果出现错误就回滚到保存点

🍒 with 语句方式

from django.db import transaction


def fun(request):
    with transaction.atomic():
        save_id = transaction.savepoint()  # 开启事务
        try:
            # 操作1
            # 操作2
            # ......
            transaction.savepoint_commit(save_id)  # 没有出现错误,提交从保存点到当前位置的所有操作
        except:
            transaction.savepoint_rollback(save_id)  # 如果出现错误就回滚到保存点

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/16518.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

PDF文件如何设置密码保护?

接近年底&#xff0c;各种总结报告越来越多&#xff0c;很多时候我们都会将报告做成PDF文件格式&#xff0c;对于重要的内容&#xff0c;往往还需要设置密码保护。 根据不同的需要&#xff0c;可以给PDF文件设置两种保护模式。 如果文件内容只分享给特定的人看&#xff0c;不…

qt调用python脚本中的函数

开发环境&#xff1a; qt 5.9.9 vs2015 python 3.6 例程下载&#xff1a; qt调用python脚本例程.rar 步骤一&#xff1a;创建python脚本文件 创建文本文件myPythonFile.py&#xff0c;内容如下&#xff1a; 步骤二&#xff1a;创建qt widget测试例程并运行 新建qt wi…

请不要忽略软件测试的业务能力

在日常的测试工作中&#xff0c;不知道大家是否会有梳理自己测试业务的习惯。我个人觉得这个事情是值得做的&#xff0c;最好还可以培养成一个习惯。一、为什么要梳理业务&#xff1f;因为在业务测试中&#xff0c;作为测试人员&#xff0c;熟悉负责的业务是非常重要的&#xf…

ats 6.2.3中diags.log日志滚存遇到的assert崩溃问题并解决

现在线上ats 6.2.3现在都开启了diags.log日志回滚的功能&#xff0c;采用下面的配置方法 CONFIG proxy.config.diags.logfile.rolling_enabled INT 3 CONFIG proxy.config.diags.logfile.rolling_interval_sec INT 86400 CONFIG proxy.config.diags.logfile.rolling_size_mb…

Web前端——立体相册的制作

文章目录笔记&#xff1a;CSS的特殊样式作业&#xff1a;用CSS的特殊样式制作立体相册笔记&#xff1a;CSS的特殊样式 media查询 常⽤于响应式布局&#xff0c;是⽬前使⽤最多的适配⻚⾯的技术。他会根据⻚⾯的尺⼨的不同&#xff0c;⽽是⽤不同的样式。 <style>media…

LeetCode50天刷题计划第二季(Day 31 — 两数之和 II - 输入有序数组(11.10-11.20)分数到小数(11.30-12.30)

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录前言一、题目两数之和 II - 输入有序数组示例提示二、思路三、代码四、题目分数到小数示例提示五、思路六、代码前言 没看出来跟 两数之和 I 有什么区别 一、题目 …

码农死磕这份Java高级开发文档,成功‘挤‘进一线大厂,这也太强了吧

前言 很多程序员一开始在学习上找不到方向&#xff0c;但我想在渡过了一段时间的新手期之后这类问题大多都会变得不再那么明显&#xff0c;工作的方向也会逐渐变得清晰起来。 但是没过多久&#xff0c;能了解到的资料就开始超过每天学习的能力&#xff0c;像是买了没看的书、…

内网渗透神器CobaltStrike之重定向服务配置(二)

重定向服务的概念 "重定向"是一个在CS服务器与目标主机进行网络传输之间的服务器, 不仅能保护CS服务器, 还能增强与目标网络传输的稳定性, 例如某一台重定向服务器倒塌了, 但是CS服务器还是能通过其他重定向服务器与目标网络进行信息传输 环境拓扑 域名: team.comD…

ELSEVIER期刊论文投稿全流程实例讲解

Elsevier期刊模板下载 从ELSEVIER搜索要投的期刊&#xff0c;进入期刊主页 https://www.elsevier.com/search-results?queryFuel

【附源码】Python计算机毕业设计体育场馆预定网站

项目运行 环境配置&#xff1a; Pychram社区版 python3.7.7 Mysql5.7 HBuilderXlist pipNavicat11Djangonodejs。 项目技术&#xff1a; django python Vue 等等组成&#xff0c;B/S模式 pychram管理等等。 环境需要 1.运行环境&#xff1a;最好是python3.7.7&#xff0c;我…

基于随机森林算法完成鸢尾花卉品种预测任务 代码+数据

1.理论部分 随机森林(Random Forest),顾名思义,就是由很多决策树模型融合在一起的算法。 随机森林是一种运用了集成学习(ensemble learning)的决策树分类器。 随机森林是一种基于Bagging框架的模型融合算法,如图1.2所示。它通过多个基础的决策树模型进行训练,如何通过…

Android App事件交互中区分点击和长按动作以及识别手势滑动方向的讲解及实战(附源码 可直接使用)

运行有问题或需要源码请点赞关注收藏后评论区留言~~~ 一、区分点击和长按动作 区分点击和长按动作&#xff0c;只要看按压时长是否超过500毫秒即可&#xff0c;没超过的表示点击动作&#xff0c;超过了的表示长按动作。其实除了按压时长之外&#xff0c;按压力度也是一个重要的…

Isaac-gym(5):关于强化学习

官方链接&#xff1a; https://github.com/NVIDIA-Omniverse/IsaacGymEnvs 1、环境建立示例 import isaacgym import isaacgymenvs import torchenvs isaacgymenvs.make(seed0, task"Ant", #对应执行时用到的名称num_envs2000, sim_device"cuda:0"…

智芯传感-工业雷管禁售在即,电子雷管的大发展已然到来!

在我国重点支持发展的基础设施建设领域中&#xff0c;民爆行业是一个相对小众、但是非常重要的行业。在“十四五”规划中&#xff0c;国家大力推进电子雷管替代工业雷管&#xff0c;持续加强激励与引导&#xff0c;推进生产工艺及装备向安全可靠、绿色环保、智能制造方向发展&a…

Makefile 基础(二)—— Makefile 自动推导+ Makefile伪目标

目录 1、Makefile 自动推导&#xff08;隐含规则&#xff09; (1) 依赖项都在当前目录下 (2) 一部分依赖项不在当前目录下 2、Makefile 伪目标 1、Makefile 自动推导&#xff08;隐含规则&#xff09; 所谓隐含规则指的是&#xff0c;我们在Makefile文件中不使用 gcc/g 命…

openTCS 5.2 学习记录一(避坑)

openTCS5.2 学习记录一 初学者记录 一、学习背景 最近领导安排学习AGV相关调度方面的东西&#xff0c;我司使用的是openTCS来做AGV调度管理。本文主要记录最简单的启动&#xff0c;并且记录使用过程中的各个坑。 二、参考资料 openTCS官网 https://www.opentcs.org/en/ind…

玩机搞机-----安卓全机型刷机卡fastboot模式解决方法与故障解析

今天给友友们讨论下手机刷机后进不去系统卡fastboot模式一些问题解决方法和造成的原因故障解析。一般这类操作是由于以下几种原因导致的。包括但不限于以下其中之一 这种故障排除硬件原因除外哦 1-----刷第三方系统导致的重启卡fastboot模式 2-----降级更新官方固件跨版本幅…

Level1行情和l2行情数据api接口在逐笔成交记录上有什么区别?

除了买卖盘口显示的行情数据不同&#xff0c;Level-1行情和l2行情数据api接口第二个主要的区别是Level-1行情只有分时成交记录而l2行情数据api接口同时还提供逐笔成交记录。 也就是说Level-1行情是不提供具体的每笔交易明细的。但是l2行情数据api接口它记录了实时交易中每一笔…

第二章:Spring核心思想和IOC和AOP依赖注入

Spring 中IOC 如何理解&#xff1f; 中文控制反转&#xff0c;如何控制反转&#xff1f; 是一种思想&#xff0c;交给Spring容器来管理的一种思想&#xff0c;具体扫描注解&#xff0c;实现注入容器内。 平时使用某个类调用某个类的内的方法&#xff0c;需要先创建类的对象&a…

E 排队(排列组合)[牛客小*白月赛61]

题面如下&#xff1a; 思路 or 题解&#xff1a; 对于一个长度为 nnn 的 排列组合 如果存在一对 逆序对 (x,y)(x, y)(x,y) xxx 在 yyy 的前面有 n∗(n−1)2\frac{n * (n - 1)}{2}2n∗(n−1)​ 种情况 剩下 n−2n - 2n−2 个位置可以随意填数进去&#xff0c;不会影响到逆序对 …