赞
踩
由模型实例化对象调用内置方法实现数据新增,比如单数据新增调用create
,查询与新增调用get_or_create
,修改与新增调用update_or_create
,批量新增调用bulk_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()
注意:
执行数据插入时,为了保证数据的有效性,我们需要对数据进行去重判断,确保数据不会重复插入。以往的方案都是对数据表进行查询操作,如果查询的数据不存在,就执行数据插入操作。
get_or_create
根据每个模型字段的值与数据表的数据进行判断,判断方式如下:
d=dict(job='测试工程师',title='系统测试',payment=10,name_id=3)
Vocation.objects.get_or_create(**d)
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'})
如果要对某个模型执行数据批量插入操作,那么可以使用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)
数据修改必须执行一次数据查询,再对查询结果进行修改操作,常用方法有:模型实例化、update
方法和批量更新bulk_update
。
v = Vocation.objects.get(id=1)
v.payment = 20000
v.save()
# 批量更新一条或多条数据,查询方法使用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)
# 新增两行数据
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种方式:删除数据表的全部数据、删除一行数据和删除多行数据,实现方式如下:
# 删除数据表中的全部数据
Vocation.objects.all().delete()
# 删除一条id为1的数据
Vocation.objects.get(id=1).delete()
# 删除多条数据
Vocation.objects.filter(job='测试员').delete()
外键删除模式说明:
数据查询分为单表查询和多表查询,Django
提供多种不同查询的API
方法,以满足开发需求。
# 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)
上述的查询条件filter
和get
是使用等值的方法来匹配结果。若想使用大于、不等于或模糊查询的匹配方法,则可在查询条件filter
和get
里使用下面所示的匹配符实现。
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]')
注意:
在日常的开发中,常常需要对多张数据表同时进行数据查询。多表查询需要在数据表之间建立表关系才能够实现。一对多或一对一的表关系是通过外键实现关联的,而多表查询分为正向查询和反向查询。
# 正向查询 # 查询模型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_related
或prefetch_related
方法实现,该方法只需执行一次SQL
查询就能实现多表查询。
select_related
主要针对一对一和一对多关系进行优化,它是使用SQL
的JOIN
语句进行优化的,通过减少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
执行SQL
语句有3种方法实现:extra
、raw
和execute
,其中extra
和raw
只能实现数据查询,具有一定的局限性;而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
语句无须经过Django
的ORM
框架。我们知道Django
连接数据库需要借助第三方模块实现连接过程,如MySQL
的mysqlclient
模块和SQLite
的sqlite3
模块等,这些模块连接数据库之后,可通过游标的方式来执行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
框架所缺失的功能,如执行数据库的存储过程。
数据库事务是指作为单个逻辑执行的一系列操作,这些操作具有原子性,即这些操作要么完全执行,要么完全不执行,常用于银行转账和火车票抢购等。
事务是指作为单个逻辑执行的一系列操作,这些操作具有原子性,即这些操作要么完全执行,要么完全不执行。事务处理可以确保事务性单元内的所有操作都成功完成,否则不会执行数据操作。
事务应该具有4个属性:原子性(Atomicity)、一致性(Consistency)、隔离性(Isolation)、持久性(Durability),这4个属性通常称为ACID特性。
Django中通过使用 atomic() 装饰器或 transaction.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')
# 如果任何数据库操作失败,事务会回滚;否则会提交
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')
# 如果任何数据库操作失败,事务会回滚;否则会提交
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。