数据表操作

数据表操作主要为增、删、改、查、执行SQL语句和实现数据库事务等操作

  • 数据新增:有模型实例化对象调用内置方法实现数据新增
  • 数据修改必须执行一次数据查询,在对查询结果进行修改操作,常用方法有:模型实例化、update方法和批量更新bulk_update
  • 数据删除必须执行一次数据查询,再查询结果进行删除操作,若删除的数据设有外键字段,则删除结果由外键的删除模式设定
  • 数据查询分为单表查询和多表查询,Django提供多种不同查询的API方法
  • 执行SQL语句有3中方法实现:extra、raw和execute,其中extra和raw只能实现数据查询,具有一定局限性;而execute无须经过ORM框架处理,能够执行所有SQL语句,但很容易受到SQL注入攻击。
  • 数据库事务是指作为单个逻辑执行的一系列操作,这些操作具有原子性,即这些操作要么完全执行,要么完全不执行,常用语银行转账和火车票抢购等。

数据新增

方法示例:

v = Vocation()
v.job = '测试工程师'
v.title = '系统测试'
v.payment = 0
v.name_id = 3
v.save()
v=Vocation.objects.create(job='测试工程师',titile='系统测试',payment=0,name_id=3)
d = dict(job='测试工程师',title='系统测试',payment=0,name_id=3)
v=Vocation.objects.create(**d)
v = Vocation(job='测试工程师',titile='系统测试',payment=0,name_id=3)
v.save()

在执行数据插入时,为了保证数据有效性,需要对数据进行去重判断,为了简化这一过程,Django提供了get_or_create方法:

d = dict(job='测试工程师',title='系统测试',payment=0,name_id=3)
v=Vocation.objects.get_or_create(**d)

同样思路,Django还提供了update_or_create方法来判断数据是否存在,若存在则更新,若不存在则新增。
还可以对某个模型执行数据批量插入操作,使用bulk_create方法实现:

v1= Vocation(job='财务',title='会计',payment=0,name_id=1)
v2= Vocation(job='财务',title='出纳',payment=0,name_id=1)
ojb_list = [v1, v2]
Vocation.objects.bulk_create(ojb_list)

数据修改

数据修改方式与数据新增步骤大致相同,唯一区别在于需要先进行一次数据查询,然后将对象的属性进行赋值处理,代码如下:

v = Vocation.objects.get(id=1)
v.payment = 20000
v.save()

其他方法:

Vocation.objects.filter(job='测试工程师').update(job='测试员')
d= dict(job='测试员')
Vocation.objects.filter(job='测试工程师').update(**d)
Vocation.objects.update(payment=666)

上面这个不进行查询,对全表所有数据全部进行更新
下面还可以使用内置F方法

frome django.db.models import F
v=Vocation.objects.filter(job='测试工程师')
v.update(payment=F('payment')+1)

同样,也可以使用bulk_update方法来实现批量修改

v1= Vocation(job='财务',title='会计',payment=0,name_id=1)
v2= Vocation(job='财务',title='出纳',payment=0,name_id=1)
v1.payment= 1000
v2.title= '行政'
Vocation.objects.bulk_update([v1,v2],fields=['payment','title'])

数据删除

数据删除有3种方式:删除数据表的全部数据,删除一行数据和删除多行数据

Vocation.objects.all().delete()
Vocation.objects.get(id=1).delete()
Vocation.objects.filter(job='测试员').delete()

请注意,如果删除的数据设有外键字段,就会同时删除关联的数据。

外键字段的参数on_delete用于设置删除数据模式(十一的补充),说明如下

  • PROTECT模式:如果删除的数据舍友外键字段并且关联其他数据表的数据,就提示数据删除失败
  • SET_NULL模式:执行数据删除并把其他数据表的外键字段设置为Null,外键字段必须将属性Null设为True,否则提示异常
  • SET_DEFAULT模式:执行数据删除并把其他数据表的外键字段设置为默认值
  • SET模式:执行数据删除并把其他数据表的外键字段关联其他数据
  • DO_NOTING模式:不做任何处理,删除结果由数据库的删除模式决定

数据查询

Django的ORM框架对不同的查询方式定义了相应的API方法,代码如下(在shell模式下使用):
数据以列表返回

from index.models import *
v = Vocation.objects.all()
v[0].job
v = Vocaton.objects.all():[:3]
v
v = Vocation.objects.values('job')
v[1]['job']
v = Vocation.objects.values_list('job')[:3]
v
v = Vocation.objects.get(id=2)
v.job
v = Vocation.objects.filter(id=2)
v[0].job

注意get和filter的区别

v = Voctaion.objects.filter(job='网站设计', id=3)
v
d = dict(job='网站设计', id=3)
v = Vocation.objects.filter(**d)
# SQL的or查询,需要引入Q,编写格式:Q(field=value)|Q(field=value)
from django.db.models import Q
v = Vocation.objects.filter(Q(job='网站设计')|Q(id=4))
v
# SQL的不等于查询,在Q前加“~”
v = Vocation.objects.filter(~Q(job='网站设计'))
v
# 还可以用exclude实现不等于查询
v = Vocation.objects.exclude(job='网站设计')
v
# 统计查询数据数据量
v = Vocation.objects.filter(job='网站设计').count()
# 去重查询,distinct方法无需设置参数,去重方式根据values设置的字段执行
v = Vocation.objects.values('job').filter(job='网站设计').distinct()
v
# 根据字段id降序排列,降序只要在order_by里面的字段前面加“-”即可
# order_by可以设置多字段排列,v = Vocation.objects.order_by('-id', 'job')
v = Vocation.objects.order_by('-id')
v
# 聚合查询,实现对数据值求和、求平均值等,由annotate和aggregate方法实现
# annotate类似于SQL里面的GROUP BY方法
# 如果不设置value,默认对主键进行GROUP BY方法
from django.db.models import Sum, Count
v = Vocation.objects.values('job').annotate(sum('id'))
print(v.query)# aggregate是计算某个字段的值并放回计算结果
from django.db.models import Count
v = Vocation.objects.aggregate(id_count=Count('id'))
v
# union、interscetion和difference语法
# 每次查询结果的字段必须相同
v1 = Vocation.objects.filter(payment__gt=9000)v2 = Vocation.objects.filter(payment__gt=5000)# 获取两次查询结果的并集
v1.union(v2)# 获取两次查询结果的交集
v1.interscetion(v2)#以v2为目标数据,去除v1和v2的共同数据
v2.diffrence(v1)

各种查询方法都是围绕在get和filter的方法来匹配,默认都是通过等值方法来实现,如果想实现大于、不等于或模糊匹配方法,可以使用匹配符来实现,如下表:

匹配符 使用 说明
__exact filter(job__exact=‘开发’) 精确等于
__iexact filter(job__iexact=‘开发’) 精确等于并忽略大小写
__contains filter(job__contains=‘开发’) 模糊匹配
__icontains filter(job__icontains=‘开发’) 精确等于并忽略大小写
__gt filter(id__gt=5) 大于
__gte filter(id__gte=5) 大于等于
__lt filter(id__lt=5) 小于
__lte filter(id__lte=5) 小于等于
__in filter(id__in=[1,2,3]) 判断是否在列表内
__startwith filter(job__startwith=‘开发’) 以…开头
__istartwith filter(job__istartwith=‘开发’) 以…开头并忽略大小写
__endwith filter(job__endwith=‘开发’) 以…结尾
__iendwith filter(job__Iendwith=‘开发’) 以…结尾并忽略大小写
__range filter(job__range=‘开发’) 在…范围内
__year filter(job__year=2018) 日期字段的年份
__month filter(job__month=12) 日期字段的月份
__day filter(job__day=30) 日期字段的天数
__isnull filter(job__isnull=True/False) 判断是否为空

但是还请区分一下get和filter的区别:

  • 查询条件get:查询字段必须是主键或者唯一约束的字段,并且查询的数据必须存在,如果查询的字段有重复值或者查询的数据不存在,程序就会抛出异常信息
  • 查询条件filter:查询字段没有限制,只要该字段是数据表的某一字段即可,查询结果以列表形式返回,如果查询结果为空(数据表中找不到),则返回空列表。

多表查询

from django.db import models# Create your models here.
class PersonInfo(models.Model):id = models.AutoField(primary_key=True)name = models.CharField(max_length=20)age = models.IntegerField()class Vocation(models.Model):id = models.AutoField(primary_key=True)job = models.CharField(max_length=20)title = models.CharField(max_length=20)# 新增一个名为payment的属性payment = models.IntegerField(null=True, blank=True)name = models.ForeignKey(PersonInfo, on_delete=models.Case)def __str__(self):return str(self.id)class Meta:verbose_name = '职业信息'

依然以上述两个模型为例,模型Vocation定义的外键字段name关联到模型PersonInfo。如果查询对象的主体是模型Vocation,通过外键字段name去查询模型PersonInfo的关联数据,那么查询称为正向查询。如果查询对象主体是模型PersonInfo,yao查询它与模型Vocation的关联数据,那么查询称为反向查询。

# 正向查询
v = Vocation.objects.filter(id=1).first()
v.name.hireDate# 反向查询
p = PersonInfo.objects.filter(id=2).first()

方法一:
vovaton_set的返回值为queryset对象,vocation_set的vocation为模型Vocation的名称小写,Vocation的外键字段name不能设置参数related_name,若设置参数则无法使用vocation_set

v  = p.vocation_set.first()
v.job

方法二:
由模型Vocation的外键字段name的参数related_name实现
外键字段name必须设置参数related_name才有效,否则无法查询
将外键参数的related_name设为personinfo

v = p.personinfo.first()
v.job

同样,数据的正想查询和反向查询也可以在查询条件里使用,这种方式用于查询条件的字段不在查询对象里的时候:

# 正向查询
v = Vocation.objects.filter(name__name='Tim').first()
v.name.hierDate
# name__name,前面的name是模型Vocation的字段name
# 后面的name是模型PersonInfo的字段name,两者用双下划线连接,v.name代表外键name
# 反向查询
p = PersonInfo.objects.filter(personinfo__job='网站设计').first()
v = p.personinfo.first()
v.job

无论是正向查询还是反向查询,他们在数据库里都要执行两次SQL查询。为了减少查询次数,提高查询效率,可以使用select_related和prefetch_related方法实现,该方法只需要执行一次查询。

select_related主要针对一对一和一对多关系进行优化,它是使用SQL和JOIN语句进行优化的,方法如下:

p = PersonInfo.objects.select_related('personinfo').values('name','personinfo__payment')
v = Vocation.objects.select_related('name'),values('name','name__age')
v = Vocation.objects.select_related('name').filter(pay_ment__gt=8000)
print(v.query)
v[0].name.age

当然,selet_related还支持3个或3个以上的数据表同时查询,下面写一个models.py里的模型

class Province(models.Model):name = models.CharField(max_length=10)def __str__(self):return str(self.name)class City(models.Model):name = models.CharField(max_length=5)province = models.ForeignKey(Province, on_delete=models.CASCADE)def __str__(self):return str(self.name)class Person(models.Model):name = models.CharField(max_length=10)living = models.ForeignKey(City, on_delete=models.CASCADE)def __str__(self):return str(self.name)

如果想查询某个居民所在省份,则要先查询所在城市,然后通过所在城市查询省份,方法如下:

p = Person.objects.select_related('living__province').get(name='Tom')
p.living.province

由此可见

  • living是模型Person的外键字段,其指向City
  • province是模型City的外键,其指向Province

两个外键之间使用双下划线连接。

prefetch_related与select_related的设计目的很相似,为了减少SQL的查询次数,但是实现方法不一样,select_related对于多对多关系会增加数据查询时间和内存占用,而prefetch_related对于查询多对多关系更有优势一些:
示例模型如下:

class Performer(models.Model):id = models.IntegerField(primary_key=True)name = models.CharField(max_length=20)nationality = models.CharField(max_length=20)def __str__(self):return str(self.name)class Program(models.Model):id = models.IntegerField(primary_key=True)name = models.CharField(max_length=20)performer = models.ManyToManyField(Performer)def __str__(self):return str(self.name)

查询方式如下:

p = Program.objects.prefetch_related('performer').filter(name='小王子'),first()
p.performer.all()

Django全栈开发学习笔记(十二)——数据的增、删、改、查相关推荐

  1. Polyworks脚本开发学习笔记(十二)-输出和读取文本文件

    Polyworks脚本开发学习笔记(十二)-输出和读取文本文件 Polyworks作为一个测量工具,将测量的数据方便的导出到文本文件则是一项必须的功能.在DATA_FILE这个命令下提供了很多子命令用 ...

  2. Web全栈开发学习笔记—Part2 与服务端通信—d.在服务端将数据Alert出来

    目录 REST Sending Data to the Server Changing the importance of notes Extracting communication with th ...

  3. Web全栈开发学习笔记—Part4 测试 Express 服务端程序, 以及用户管理—d.密钥认证

    目录 Limiting creating new notes to logged in users Error handling 现在将让后端支持基于令牌的认证下面的时序图描述了基于令牌认证的原理: ...

  4. Polyworks脚本开发学习笔记(十六)-用C#进行Polyworks二次开发

    Polyworks脚本开发学习笔记(十六)-用C#进行Polyworks二次开发 Polyworks支持C#二次开发,用对应的SDK文档试着做一下开发样例. 新建一个C#项目,在解决方案中右键添加引用 ...

  5. Python全栈工程师学习笔记 | Django的模型层

    Model模型 模型是你的数据的唯一的.权威的信息源.它包含你所储存数据的必要字段和行为. 通常,每个模型对应数据库中唯一的一张表. 每个模型都是django.db.models.Model的一个Py ...

  6. python datetime需要安装_Python全栈工程师学习笔记 | Django的模型层

    Model模型 模型是你的数据的唯一的.权威的信息源.它包含你所储存数据的必要字段和行为. 通常,每个模型对应数据库中唯一的一张表. 每个模型都是django.db.models.Model的一个Py ...

  7. 《C++游戏开发》笔记十二 战争迷雾:初步实现

    本系列文章由七十一雾央编写,转载请注明出处. http://blog.csdn.net/u011371356/article/details/9475979 作者:七十一雾央 新浪微博:http:// ...

  8. Python语言入门这一篇就够了-学习笔记(十二万字)

    Python语言入门这一篇就够了-学习笔记(十二万字) 友情提示:先关注收藏,再查看,12万字保姆级 Python语言从入门到精通教程. 文章目录 Python语言入门这一篇就够了-学习笔记(十二万字 ...

  9. windows内核开发学习笔记十五:IRP结构

    windows内核开发学习笔记十五:IRP结构   IRP(I/O Request Package)在windows内核中,有一种系统组件--IRP,即输入输出请求包.当上层应用程序需要访问底层输入输 ...

最新文章

  1. 口罩告急,全民互助!“口罩互助”小程序重磅上线!
  2. ASP.Net Core Razor 页面路由
  3. 你必须知道的CSS盒模型,顺利通过阿里面试
  4. Linux 编译安装Boost
  5. Asp.net的生命周期之应用程序生命周期
  6. 日语输入法电脑版_哪个日语输入法比较好用,日语输入法下载及使用教程
  7. 如何构建“正确的”云平台存储
  8. 免费JSON格式的服务接口
  9. C语言程序中数字字符是什么,C语言中如何识别字符与数字
  10. 武田宣布就拟收购Shire plc签署优先短期贷款工具协议及次级银团贷款协议和过桥信贷协议第二次修订
  11. yutons_sug搜索框提示插件||输入框提示插件
  12. 口语对话 谈判的基本技巧
  13. jenkins环境配置
  14. OpenCV各版本差异
  15. 专业名词解释 - DNS,A记录,子域名,CNAME别名,PTR,MX,TXT,SRV 记录,TTL
  16. 苹果系统和安卓系统的区别_#你喜欢苹果系统还是安卓系统?
  17. Java的诞生以及发展
  18. 原型制作软件 Axure RP
  19. (附源码)计算机毕业设计SSM理想电子商城网站
  20. 大家注意到QQ迷你新闻中的一项技术了吗?

热门文章

  1. 计算机二级考试2021考试时间黑龙江,2021年3月黑龙江计算机等级考试时间是什么时候...
  2. 他们曾经是“笑话”,如今却成了“神话”!
  3. 微软又给我们证明了竞争才有创新!
  4. 6个超级无敌实用APP,每一个都是百里挑一
  5. 功能性食品误区重重,如何辨别市面如KOKOGOOD新功能食品
  6. Nginx反向代理多个域名
  7. 企业工厂为什么要做能源管控系统
  8. RISC-V “V” 拓展—1.0版本环境搭建与测试
  9. 张德芬《遇见未知的自己》
  10. 上传自己库到Cocoapods和遇见的各种问题解决