系列文章目录
[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 语句方式
在Django MVT设计模式中的Model,专门负责和数据库进行交互,对应的文件 models.py。Model中内嵌了ORM框架,使得我们不需要直接面向数据库编程,而是定义模型类,通过模型类和对象完成数据库表的增删改查。
ORM框架就是把数据库表中的行与相应模型类的对象相对应,把数据库中的表与模型类相对应,把数据库中表的字段与模型类的属性相对应。

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

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对应femaleGENDER_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='图书') # 引用外键,引用的模型为BookInfois_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()方法可以一次性查询出模型对应的数据表中所有的数据,且该方法返回的结果为QuerySet对象。
all()方法返回的QuerySet对象是一个由数据表中所有数据记录组成的列表。
🌰 1.导入模型类:
from subapp01.models import BookInfo # 导入模型
🌰 2.通过objects调用all()方法获取BookInfo模型对应数据表中的所有数据
books = BookInfo.objects.all()

注意,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
>>> book.name
'射雕英雄传'
>>> book.read_count
12
>>>
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
'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']
'射雕英雄传'
>>>
该方法用于去除重复数据,返回的为一个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
'is_delete': False}]>
>>>
该方法返回查询结果中数据记录的数量。
🌰 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()进行过滤查询相当于SQL中的where语句
select * from 表 where 条件语句
filter():筛选符合条件的n个结果(n的取值为0-n)。返回结果为一个QuerySet对象,该对象是一个由数据记录组成的列表。
get():筛选符合条件的1个结果(返回结果只能一个,大于一个会报错),返回一个数据记录对象
exclude():排除掉符合条件之后剩下的数据组成的结果集,该结果集是一个QuerySet对象,该对象是一个由数据记录组成的列表,相当于条件语句中not。
以filter()为例
filter(字段名__运算符=值)
字段名和运算符间使用两个下划线进行分割,所以属性名不能包括多个下划线。
i表示不区分大小写,如iexact、icontains、istartswith、iendswith.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对象,该对象是一个由数据记录组成的列表。

# 查询书名包含'湖'的图书
# 不知道返回结果有几个,使用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])

# 查询编号大于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对象被定义在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)

如果需要实现逻辑或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在被关联的模型中自动生成添加用于进行反向操作的属性 关联模型类名小写 进行关联查询。
可以将关联的模型数据提取出来,可以减少数据库查询的次数。
用于一到多的关联查询
主表模型.objects.select_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)

🌰 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()

对数据进行增删改查都可以通过调用模型类的模型管理类对象objects来实现
🌰 1.导入模型类:
from subapp01.models import BookInfo # 导入模型
🌰 2.调用objects的create()方法直接新增数据对象入库
objects的create()方法会把新增的数据对象返回给我们
BookInfo.objects.create(name='css3',pub_date='2010-01-01'# 其他属性有默认值,这边就不进行赋值了
)


对数据进行增删改查都可以通过调用模型类的模型管理类对象objects来实现
🌰 1.导入模型类:
from subapp01.models import BookInfo # 导入模型
🌰 2.获取模型对象
# 查询(获取)出需要进行修改的数据对象 获取id=1的数据对象
book = BookInfo.objects.get(id=1)
🌰 3.修改获取到的实例对象的属性
book.read_count = 2000
🌰 4.调用save()方法将修改后的数据同步数据库
book.save()

🌰 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()方法更新数据。
🌰 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)



🌰 1.导入模型类:
from subapp01.models import BookInfo # 导入模型
🌰 2.获取指定的模型数据对象
book = BookInfo.objects.get(id=5)
🌰 3.获取到的模型数据对象调用delete()方法将自己删除
该方法会返回一个元组类型的数据,元组的第一个元素为本次操作删除的所有表的总行数之和,元组的第二个元素为字典类型,字典中为每个表在本次操作分别删除了几行数据
book.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()

当ORM提供的API无法实现数据的查询时,需要使用原生的SQL语句进行数据的查询,此时我们可以通过执行原生SQL实现数据的查询。
在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 BookInfosql = """
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
# 返回的结果集可以使用列表下标的方式获取数据对象
>>> books[0]
>>> books[1]
>>>
在Django中,django.db.connection中封装了数据库的连接对象,我们可以通过数据库的连接对象获取游标,然后通过获取的游标来执行原生SQL语句实现对数据库的增删改查。
获取数据库的连接对象:
from django.db import connection
通过数据库的连接对象获取游标:
cursor = connection.cursor()
使用游标执行原生sql语句:
cursor.execute(sql, [填充占位符的数据])
关闭游标:
cursor.close()
from django.db import connectioncursor = 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
>>> cursor.close()

游标对象提供了fetchall()方法用于获取执行sql语句后的全部数据,返回的结果为所有数据对象各字段数据组成的元组形成的列表;以及fetchone()方法用于获取其中的一个结果,第一次执行获取第一条数据记录,此后每执行一次都会返回下一条数据记录,直到所有的数据记录都获取过为止,每次返回的结果为数据对象各字段数据组成的元组。
from django.db import connectionsql = "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 connectionsql = "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 connectionsql = "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) # 如果出现错误就回滚到保存点
from django.db import transactiondef fun(request):with transaction.atomic():save_id = transaction.savepoint() # 开启事务try:# 操作1# 操作2# ......transaction.savepoint_commit(save_id) # 没有出现错误,提交从保存点到当前位置的所有操作except:transaction.savepoint_rollback(save_id) # 如果出现错误就回滚到保存点
上一篇:控制的对立面是什么