django学习-数据表操作

一、数据表操作

1. 数据新增

由模型实例化对象调用内置方法实现数据新增,比如单数据新增调用create,查询与新增调用get_or_create,修改与新增调用update_or_create,批量新增调用bulk_create

1.1 create()
复制代码
# 方法一
# 使用create方法实现数据插入
Vocation.objects.create(job='测试工程师',title='系统测试',
payment=0,name_id=3)

# 方法二
# 同样使用create方法,但数据以字典格式表示
d=dict(job='测试工程师',title='系统测试',payment=0,name_id=3)
Vocation.objects.create(**d)

# 方法三
# 在实例化时直接设置属性值
v=Vocation(job='测试工程师',title='系统测试',payment=0,name_id=3)
v.save()

注意:

执行数据插入时,为了保证数据的有效性,我们需要对数据进行去重判断,确保数据不会重复插入。以往的方案都是对数据表进行查询操作,如果查询的数据不存在,就执行数据插入操作。

1.2 get_or_create()

get_or_create根据每个模型字段的值与数据表的数据进行判断,判断方式如下:

  1. 只要有一个模型字段的值与数据表的数据不相同(除主键之外),就会执行数据插入操作。

  2. 如果每个模型字段的值与数据表的某行数据完全相同,就不执行数据插入,而是返回这行数据的数据对象。

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

1.3 update_or_create()

update_or_create方法判断当前数据在数据表里是否存在,若存在,则进行更新操作,否则在数据表里新增数据。

复制代码
# 第一次是新增数据
d=dict(job='软件工程师',title='Java开发',name_id=2,payment=8000)
v=Vocation.objects.update_or_create(**d)
# 第二次是修改数据
v=Vocation.objects.update_or_create(**d,defaults={'title': 'Java'})
1.4 bulk_create()

如果要对某个模型执行数据批量插入操作,那么可以使用bulk_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)
2. 数据修改

数据修改必须执行一次数据查询,再对查询结果进行修改操作,常用方法有:模型实例化、update方法和批量更新bulk_update

2.1 模型实例化
复制代码
v = Vocation.objects.get(id=1)
v.payment = 20000
v.save()
2.2 update()
复制代码
# 批量更新一条或多条数据,查询方法使用filter
# filter以列表格式返回,查询结果可能是一条或多条数据
Vocation.objects.filter(job='测试工程师').update(job='测试员')
# 更新数据以字典格式表示
d= dict(job='测试员')
Vocation.objects.filter(job='测试工程师').update(**d)
# 不使用查询方法,默认对全表的数据进行更新
Vocation.objects.update(payment=6666)
# 使用内置F方法实现数据的自增或自减
# F方法还可以在annotate或filter方法里使用
from django.db.models import F
v=Vocation.objects.filter(job='测试工程师')
# 将payment字段原有的数据自增加一
v.update(payment=F('payment')+1)
2.3 bulk_create()
复制代码
# 新增两行数据
v1=Vocation.objects.create(job='财务',title='会计',name_id=1)
v2=Vocation.objects.create(job='财务',title='出纳',name_id=1)
# 修改字段payment和title的数据
v1.payment=1000
v2.title='行政'
# 批量修改字段payment和title的数据
Vocation.objects.bulk_update([v1,v2],fields=['payment','title'])
3. 数据删除

数据删除必须执行一次数据查询,再对查询结果进行删除操作,若删除的数据设有外键字段,则删除结果由外键的删除模式决定。

数据删除有3种方式:删除数据表的全部数据、删除一行数据和删除多行数据,实现方式如下:

复制代码
# 删除数据表中的全部数据
Vocation.objects.all().delete()
# 删除一条id为1的数据
Vocation.objects.get(id=1).delete()
# 删除多条数据
Vocation.objects.filter(job='测试员').delete()

外键删除模式说明:

  1. PROTECT模式:如果删除的数据设有外键字段并且关联其他数据表的数据,就提示数据删除失败。
  2. SET_NULL模式:执行数据删除并把其他数据表的外键字段设为Null,外键字段必须将属性Null设为True,否则提示异常。
  3. SET_DEFAULT模式:执行数据删除并把其他数据表的外键字段设为默认值。
  4. SET模式:执行数据删除并把其他数据表的外键字段关联其他数据。
  5. DO_NOTHING模式:不做任何处理,删除结果由数据库的删除模式决定。
  6. CASCADE模式:执行数据删除时会删除所有依赖于这条记录的从表中的相关记录,更新时也会更新所有从表中的记录。
4. 数据查询

数据查询分为单表查询和多表查询,Django提供多种不同查询的API方法,以满足开发需求。

4.1 单表查询
复制代码
# SQL:Select * from index_vocation,数据以列表返回
v = Vocation.objects.all()
# 查询第一条数据,序列从0开始
v[0].job
# 查询前3条数据
# SQL:Select * from index_vocation LIMIT 3
# SQL语句的LIMIT方法,在Django中使用列表截取即可
v = Vocation.objects.all()[:3]
# 查询某个字段
# SQL:Select job from index_vocation
# values方法,数据以列表返回,列表元素以字典表示
v = Vocation.objects.values('job')
v[1]['job']
# values_list方法,数据以列表返回,列表元素以元组表示
v = Vocation.objects.values_list('job')[:3]
# 使用get方法查询数据
# SQL:Select*from index_vocation where id=2
v = Vocation.objects.get(id=2)
# 使用filter方法查询数据,注意区分get和filter的差异
v = Vocation.objects.filter(id=2)
v[0].job
# SQL的and查询主要在filter里面添加多个查询条件
v = Vocation.objects.filter(job='网站设计', id=3)
#filter的查询条件可设为字典格式
d=dict(job='网站设计', id=3)
v = Vocation.objects.filter(**d)
# SQL的or查询,需要引入Q,编写格式:Q(field=value)|Q(field=value)
#多个Q之间使用"|"隔开即可
# SQL:Select * from index_vocation where job='网站设计' or id=9
from django.db.models import Q
v = Vocation.objects.filter(Q(job='网站设计')|Q(id=4))
# SQL的不等于查询,在Q查询前面使用"~"即可
# SQL语句:SELECT * FROM index_vocation WHERE NOT (job='网站设计')
v = Vocation.objects.filter(~Q(job='网站设计'))
#还可以使用exclude实现不等于查询
v = Vocation.objects.exclude(job='网站设计')
# 使用count方法统计查询数据的数据量
v = Vocation.objects.filter(job='网站设计').count()
# 去重查询,distinct方法无须设置参数,去重方式根据values设置的字段执行
# SQL:Select DISTINCT job from index_vocation where job = '网站设计'
v = Vocation.objects.values('job').filter(job='网站设计').distinct()
# 根据字段id降序排列,降序只要在order_by里面的字段前面加"-"即可
# order_by可设置多字段排列,如Vocation.objects.order_by('-id', 'job')
v = Vocation.objects.order_by('-id')
# 聚合查询,实现对数据值求和、求平均值等。由annotate和aggregate方法实现
# annotate类似于SQL里面的GROUP BY方法
#如果不设置values,默认对主键进行GROUP BY分组
# SQL:Select job,SUM(id) AS 'id__sum' from index_vocation GROUP BY job
from django.db.models import Sum, Count
v = Vocation.objects.values('job').annotate(Sum('id'))
# aggregate是计算某个字段的值并只返回计算结果
# SQL:Select COUNT(id) AS 'id_count' from index_vocation
from django.db.models import Count
v = Vocation.objects.aggregate(id_count=Count('id'))
# union、intersection和difference语法
# 每次查询结果的字段必须相同
# 第一次查询结果v1
v1 = Vocation.objects.filter(payment__gt=9000)
# 第二次查询结果v2
v2 = Vocation.objects.filter(payment__gt=5000)
# 使用SQL的UNION来组合两个或多个查询结果的并集
# 获取两次查询结果的并集
v1.union(v2)
# 使用SQL的INTERSECT来获取两个或多个查询结果的交集
# 获取两次查询结果的交集
v1.intersection(v2)
# 使用SQL的EXCEPT来获取两个或多个查询结果的差
# 以v2为目标数据,去除v1和v2的共同数据
v2.difference(v1)

上述的查询条件filterget是使用等值的方法来匹配结果。若想使用大于、不等于或模糊查询的匹配方法,则可在查询条件filterget里使用下面所示的匹配符实现。

  • 精确匹配:Author.objects.filter(name__exact='John Doe')
  • 模糊匹配:Author.objects.filter(name__iexact='john doe')
  • 不等于:Author.objects.filter(name__ne='John Doe')
  • 包含:Author.objects.filter(name__contains='John')
  • 不区分大小写的包含:Author.objects.filter(name__icontains='john')
  • 正则表达式匹配:Author.objects.filter(name__regex=r'^[A-Za-z]')

注意:

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

在日常的开发中,常常需要对多张数据表同时进行数据查询。多表查询需要在数据表之间建立表关系才能够实现。一对多或一对一的表关系是通过外键实现关联的,而多表查询分为正向查询反向查询

复制代码
# 正向查询
# 查询模型Vocation某行数据对象v
v = Vocation.objects.filter(id=1).first()
# v.name代表外键name
# 通过外键name去查询模型PersonInfo所对应的数据
v.name.hireDate
# 反向查询
# 查询模型PersonInfo某行数据对象p
p = PersonInfo.objects.filter(id=2).first()
# 方法一
# vocation_set的返回值为queryset对象,即查询结果
# vocation_set的vocation为模型Vocation的名称小写
# 模型Vocation的外键字段name不能设置参数related_name
# 若设置参数related_name,则无法使用vocation_set
v = p.vocation_set.first()
v.job
# 方法二
# 由模型Vocation的外键字段name的参数related_name实现
# 外键字段name必须设置参数related_name才有效,否则无法查询
# 将外键字段name的参数related_name设为personinfo
v = p.personinfo.first()
v.job

为了减少查询次数,提高查询效率,我们可以使用select_relatedprefetch_related方法实现,该方法只需执行一次SQL查询就能实现多表查询。

select_related主要针对一对一和一对多关系进行优化,它是使用SQLJOIN语句进行优化的,通过减少SQL查询的次数来进行优化和提高性能,其使用方法如下:

复制代码
# select_related方法,参数为字符串格式
# 以模型PersonInfo为查询对象
# select_related使用LEFT OUTER JOIN方式查询两个数据表
# 查询模型PersonInfo的字段name和模型Vocation的字段payment
# select_related参数为personinfo,代表外键字段name的参数related_name
# 若要得到其他数据表的关联数据,则可用双下画线"__"连接字段名
# 双下画线"__"连接字段名必须是外键字段名或外键字段参数related_name
p=PersonInfo.objects.select_related('personinfo').
values('name','personinfo__payment')
# 查看SQL查询语句
print(p.query)
# 以模型Vocation为查询对象
# select_related使用INNER JOIN方式查询两个数据表
# select_related的参数为name,代表外键字段name
v=Vocation.objects.select_related('name').values('name','name__age')
# 查看SQL查询语句
print(v.query)
# 获取两个模型的数据,以模型Vocation的payment大于8000为查询条件
v=Vocation.objects.select_related('name').
filter(payment__gt=8000)
# 查看SQL查询语句
print(v.query)
# 获取查询结果集的首个元素的字段age的数据
# 通过外键字段name定位模型PersonInfo的字段age
v[0].name.age
6. 执行SQL语句

执行SQL语句有3种方法实现:extrarawexecute,其中extraraw只能实现数据查询,具有一定的局限性;而execute无须经过ORM框架处理,能够执行所有SQL语句,但很容易受到SQL注入攻击。

  • extra:结果集修改器,一种提供额外查询参数的机制。
    extra适合用于ORM难以实现的查询条件,将查询条件使用原生SQL语法实现,此方法需要依靠模型对象,在某程度上可防止SQL注入

    查询字段job等于'网站设计'的数据

    params为where的%s提供数值

    Vocation.objects.extra(where=["job=%s"],params=['网站设计'])
    <QuerySet [<Vocation: 3>]>

    新增查询字段seat,select_params为select的%s提供数值

    =Vocation.objects.extra(select={"seat":"%s"},
    select_params=['seatInfo'])
    print(v.query)

    连接数据表index_personinfo

    v=Vocation.objects.extra(tables=['index_personinfo'])
    print(v.query)

  • raw:执行原始SQL并返回模型实例对象。
    raw的语法和extra所实现的功能是相同的,只能实现数据查询操作,并且也要依靠模型对象,但从使用角度来说,raw更为直观易懂。

    v = Vocation.objects.raw('select * from index_vocation')
    v[0]
    <Vocation: 1>

  • execute:直接执行自定义SQL
    execute的语法,它执行SQL语句无须经过DjangoORM框架。我们知道Django连接数据库需要借助第三方模块实现连接过程,如MySQLmysqlclient模块和SQLitesqlite3模块等,这些模块连接数据库之后,可通过游标的方式来执行SQL语句,而execute就是使用这种方式执行SQL语句

    from django.db import connection
    cursor=connection.cursor()

    执行SQL语句

    cursor.execute('select * from index_vocation')

    读取第一行数据

    cursor.fetchone()

    读取所有数据

    cursor.fetchall()

execute能够执行所有的SQL语句,但很容易受到SQL注入攻击,一般情况下不建议使用这种方式实现数据操作。尽管如此,它能补全ORM框架所缺失的功能,如执行数据库的存储过程。

7. 数据库事务

数据库事务是指作为单个逻辑执行的一系列操作,这些操作具有原子性,即这些操作要么完全执行,要么完全不执行,常用于银行转账和火车票抢购等。

事务是指作为单个逻辑执行的一系列操作,这些操作具有原子性,即这些操作要么完全执行,要么完全不执行。事务处理可以确保事务性单元内的所有操作都成功完成,否则不会执行数据操作。

事务应该具有4个属性:原子性(Atomicity)、一致性(Consistency)、隔离性(Isolation)、持久性(Durability),这4个属性通常称为ACID特性。

Django中通过使用 atomic() 装饰器或 transaction.atomic() 上下文管理器来包装需要事务处理的代码块。

  1. 使用 atomic() 装饰器:

    from django.db import transaction

    @transaction.atomic
    def view_func(request):
    # 在此函数内的数据库操作会被自动包装在事务中
    obj1 = MyModel.objects.create(field1='value1', field2='value2')
    obj2 = AnotherModel.objects.create(field='value')
    # 如果任何数据库操作失败,事务会回滚;否则会提交

  2. 使用 transaction.atomic() 上下文管理器:

    from django.db import transaction

    def view_func(request):
    with transaction.atomic():
    # 在此块内的数据库操作会被包装在事务中
    obj1 = MyModel.objects.create(field1='value1', field2='value2')
    obj2 = AnotherModel.objects.create(field='value')
    # 如果任何数据库操作失败,事务会回滚;否则会提交

相关推荐
立志成为大牛的小牛3 分钟前
数据结构——三十一、最小生成树(王道408)
数据结构·学习·程序人生·考研·算法
vivo互联网技术10 分钟前
Redis key 消失之谜
数据库·redis·内存淘汰策略·redis抓包分析·机制分析
TDengine (老段)25 分钟前
TDengine 数据函数 TAN 用户手册
java·大数据·数据库·物联网·时序数据库·tdengine·涛思数据
TDengine (老段)27 分钟前
TDengine 数学函数 SQRT 用户手册
java·大数据·数据库·物联网·时序数据库·tdengine·1024程序员节
档案宝档案管理39 分钟前
零售行业档案管理的痛点与解决方案:档案管理系统显身手
大数据·数据库·人工智能·档案·零售·档案管理
艾菜籽1 小时前
MyBatis动态sql与留言墙联系
java·数据库·sql·spring·mybatis
weixin_307779131 小时前
C#程序实现将Teradata的存储过程转换为Amazon Redshift的pgsql的存储过程
数据库·c#·云计算·运维开发·aws
青~1 小时前
sql 双游标循环
数据库·sql
Every exam must be1 小时前
10.27 JS学习12
开发语言·javascript·学习
一辉ComeOn1 小时前
【大数据高并发核心场景实战】 数据持久化层 - 查询分离
java·大数据·数据库·elasticsearch·缓存·oracle