事务
#事务
from django.db import transaction
from django.db.models import F
# 装饰器用法:
@transaction.atomic
def viewfunc(request):
# 这些代码会在一个事务中执行
...
# with用法
try:
#开启事物之后只有在事物里面的代码都正确运行完成才会执行相应的操作
with transaction.atomic():
#创建一条数据
models.Order.objects.create(num='1111223444',count=1,product_id=5)
#去产品表,将卖出+1,库存-1
models.Product.objects.filter(id=5).update(kucun=F('kucun')-1,maichu=F('maichu')+1)
except Exception as e:
print(e)
#不开启事务,会一步步的执行代码碰到bug才停止
try:
# 创建一条数据
models.Order.objects.create(num='1111223455', count=1, product_id=5)
# 去产品表,将卖出+1,库存-1
models.Product.objects.filter(id=5).update(kucun=F('kucun') - 1, maichu=F('maichu') + 1)
except Exception as e:
print(e)
#常见的例子:银行取款和转账,只有整个执行过程都正确才会执行操作
1. F() ---- 专门取对象中某列值的操作
F()允许Django在未实际链接数据的情况下具有对数据库字段的值的引用。通常情况下我们在更新数据时需要先从数据库里将原数据取出后方在内存里,然后编辑某些属性,最后提交。例如
order = Order.objects.get(orderid='123456789')
order.amount += 1
order.save()
F()操作在 obj.save() 后会持续存在
如果times的值是1,那么经过n次save()之后,times的值是2
obj = models.Test.objects.get(name="cox")
obj.times = obj.times + 1
obj.save()
obj.save()
obj.save()
如果times的值是1,那么经过n次save()之后,times的值是1+n,而不是2,就是因为F()操作在 obj.save() 后会持续存在
obj = models.Test.objects.get(name="cox")
obj.times = F("times") + 1
obj.save()
obj.save()
obj.save()
F()再过滤(filter)中的使用
获取表中收入(input_price)大于支出(output_price)的数据
models.Test.objects.filter(input_price__gt=F(“output_price”))
Django支持F()对象使用加、减、乘、除、取模和幂运算等算术操作,两个操作数可以是常数或F()对象
models.Test.objects.filter(input_price__gt=F(“output_price”)*2) models.Test.objects.filter(input_price__gt=F(“output_price”)+F(“output_price”))
你还可以在F()对象中使用双下划线标记来跨越关联关系。 带有双下划线的F()对象将引入任何需要的join 操作以访问关联的对象
models.Test.objects.filter(authors__name=F(‘blog__name’))
对于date 和date/time 字段,你可以给它们加上或减去一个timedelta对象
from datetime import timedelta models.Test.objects.filter(mod_date__gt=F(‘pub_date’) + timedelta(days=3))
2. Q() ---- 对对象的复杂查询
Q对象(django.db.models.Q)可以对关键字参数进行封装,从而更好地应用多个查询。可以组合使用 &(and),|(or),~(not)操作符,当一个操作符是用于两个Q的对象,它产生一个新的Q对象。
from django.db.models import Q
models.Author.objects.filter(Q(name="cox") | Q(name="Tom")) # 获取在Author表中,name等于cox和name等于cox的所有数据
models.Author.objects.filter(Q(name="cox") & Q(age=12))# 获取在Author表中,name等于cox并且age等于12的所有数据
Q()传入条件查询
q1 = Q()
q1.connector = 'OR'
q1.children.append(('name', "cox"))
q1.children.append(('name', "Tom"))
q1.children.append(('name', "Jeck"))
models.Author.objects.filter(q1) # 在Author表中,name等于cox/Tom/Jeck的所有数据
con = Q()
q1 = Q()
q1.connector = 'OR'
q1.children.append(('name', "cox"))
q1.children.append(('name', "Tom"))
q1.children.append(('name', "Jeck"))
q2 = Q()
q2.connector = 'OR'
q2.children.append(('age', 12))
con.add(q1, 'AND')
con.add(q2, 'AND')
models.Author.objects.filter(con) # 在Author表中,name等于cox/Tom/Jeck的 并且 满足age等于12 的所有数据
Q()非
在Q()语句中,~代表非
models.Author.objects.filter(~Q(name=”cox”)) # 获取在Author表中,name不等于cox的所有数据
Q对象可以与关键字参数查询一起使用,不过一定要把Q对象放在关键字参数查询的前面。
正确写法:
Order.objects.get(
Q(create_time=date(2016, 10, 2)) | Q(create_time=date(2016, 10, 6))
desc__startswith='Who',)
错误写法:
Order.objects.get(
desc__startswith='Who',
Q(create_time=date(2016, 10, 2)) | Q(create_time=date(2016, 10, 6)))
Django Q()表达式
补充知识:Django 中 Models 的 F()和 Q()函数
1、F() —- 专门取对象中某列值的操作
F对象允许Django在未实际链接数据的情况下具有对数据库字段的值的引用。
通常情况下我们在更新数据时需要先从数据库里将原数据取出后方在内存里,然后编辑某些属性,最后提交。
all = BookInfo.objects.filter(auth="小明")
for b in all:
price = b.price
b.price = price + 10
b.save
# 使用F对象来计算
BookInfo.objects.filter(auth="小明").update(price=F("price")+10)
2、Q() —- 对对象的复杂查询
Q对象是Django对model查询中所使用的关键字参数进行封装后的一个对象。
Q对象可以通过 &(与)、 |(或)、 ~(非)运算来组合生成不同的Q对象,便于在查询操作中灵活地运用。
from django.db.models import Q
# 并且条件:与条件查询
models.User.objects.filter(条件1,条件2,条件n..)
models.User.objects.filter(Q(username='老王') & Q(userpass='admin'))
# 或者条件:或条件
models.User.objects.fliter(Q(username='老王') | Q(username='老李'))
# 取反条件
models.User.objects.filter(~Q(username='老王'))
models.User.objects.exclude(username='老王')
from django.db.models import F,Q
# 查询评论数大于100的所有书籍名称
# ret=Book.objects.filter(comment_count__gt=100).values("title")
# 查询评论数大于点赞数的所有书籍名称
# ret = Book.objects.filter(comment_count__gt=F("like_count")).values("title")
# print(ret)
# < QuerySet[{'title': 'linux'}, {'title': 'go'}] >
# 查询评论数大于2倍点赞数的所有书籍名称
# ret = Book.objects.filter(comment_count__gt=F("like_count")*2).values("title")
# SELECT `app01_book`.`title` FROM `app01_book`
# WHERE `app01_book`.`comment_count` > (`app01_book`.`like_count` * 2)
# LIMIT 21;
# print(ret) # <QuerySet []>
# 给每本书籍的价格提升100
# Book.objects.all().update(price=100+F("price"))
# 查询价格大于200或者评论数并且1000 的书籍
# ret=Book.objects.filter(price__gt=200,comment_count__gt=1000)
# SELECT `app01_book`.`nid`, `app01_book`.`title`, `app01_book`.`price`, `app01_book`.`pub_date`,
# `app01_book`.`comment_count`, `app01_book`.`like_count`, `app01_book`.`publish_id`
# FROM `app01_book`
# WHERE(`app01_book`.`comment_count` > 1000 AND `app01_book`. `price` > 200)
# LIMIT 21;
# print(ret)
# < QuerySet[ < Book: linux >, < Book: javaaaaa >] >
# 查询价格大于200或者评论数不大于1000 的书籍
# 与& 或| 非~
# ret=Book.objects.filter(Q(price__gt=200)|~Q(comment_count__gt=1000))
# SELECT `app01_book`.`nid`, `app01_book`.`title`, `app01_book`.`price`, `app01_book`.`pub_date`,
# `app01_book`.`comment_count`, `app01_book`.`like_count`, `app01_book`.`publish_id`
# FROM `app01_book`
# WHERE(`app01_book`. `price` > 200 OR NOT(`app01_book`. `comment_count` > 1000))
# LIMIT 21;
# print(ret)
# < QuerySet[ < Book: linux >, < Book: javaaaaa >, < Book: go >, < Book: go >] >
ret=Book.objects.filter(Q(Q(price__gt=200)|~Q(comment_count__gt=1000))&Q(like_count__gt=100))
# 相当于
# ret=Book.objects.filter(Q(Q(price__gt=200)|~Q(comment_count__gt=1000)),Q(like_count__gt=100))
# SELECT `app01_book`.`nid`, `app01_book`.`title`, `app01_book`.`price`, `app01_book`.`pub_date`,
# `app01_book`.`comment_count`, `app01_book`.`like_count`, `app01_book`.`publish_id`
# FROM `app01_book`
# WHERE((`app01_book`.`price` > 200 OR NOT (`app01_book`.`comment_count` > 1000))
# AND `app01_book`.`like_count` > 100)
# LIMIT 21;
print(ret)
# < QuerySet[ < Book: javaaaaa >, < Book: go >] >
return HttpResponse("查询成功")