F与Q查询
F查询
当我们需要将两个字段对应的数据进行比较时就需要用到F查询。
select * from book where sold > stock
1、例如需要将售出部分数据和库存数据进行比较时,这在ORM中怎么表达出来呢?
首先需要导入一下模块:
from django.db.models import F,Q
res = models.Book.objects.filter(sold__gt=F('stock'))
# <QuerySet [<Book: 雪山飞狐>, <Book: 活着>]>
将一个字段和另一个字段进行比较,前面还是按照正常的ORM语法,等号后面写成F('字段名')。
F查询除了可以比较两个字段的数据,还可以用来更改某个字段全部的数据。
2、将所有书籍的价格提升10元
models.Book.objects.update(price=F('price')+10)
# 对应的sql语句:update book set price = price + 500
3、在《雪山飞狐》的名称后面加上”(打折)“两字
这里需要注意的是,字符串的拼接不可以在字段后面直接用+拼接,这是错误的,会导致该字段的所有数据被清空。
我们需要导入一下两个模块。
from django.db.models import Value
from django.db.models.functions import Concat
models.Book.objects.filter(title='雪山飞狐').update(title=Concat(F('title'), Value('打折')))
# Concat模块对两个字符串进行拼接
Q查询
ORM中的filter()方法,逗号之间的条件表示的是and关系,当我们需要表达or关系的时候,就需要用到Q查询了。
导入模块:
from django.db.models import Q
查询出售出大于500或者库存小于300的书籍
res = models.Book.objects.filter(Q(sold__gt=500) | stock__lt=300)
print res
# <QuerySet [<Book: 活着>, <Book: 红楼梦>]>
# 逗号隔开表示的是and关系,|表示的是or关系
# res = models.Book.objects.filter(~Q(maichu__gt=100) | ~Q(price__lt=600)) # ~表示的是取反关系, not
ORM开启事物
事物的特性
-
原子性
指事物的不可分割性,一个事物要么全部被执行完,要么全部也不执行。
-
一致性
事物的执行使数据库由一种正确状态转换到另一种正确状态。
-
隔离性
在事物正确提交之前,不允许把该事物对数据的改变提交给任何其它事物。
-
持久性
事物提交之后其结果将保存在数据库当中,即使后面出问题了,事物的处理结果也会得到保存。
事务就是被绑定在一起作为一个逻辑工作单元的SQL语句分组,如果任何一个语句操作失败那么整个操作就被失败,以后操作就会回滚到操作前状态,或者是上有个节点。为了确保要么执行,要么不执行,就可以使用事务。要将有组语句作为事务考虑,就需要通过ACID测试,即原子性,一致性,隔离性和持久性。
ORM开启事物的方法
from django.db import transaction
try:
with transaction.atomic():
pass
# sql1
# sql2
"""
在事务中,尽量只写SQL语句, 业务逻辑代码写在事务外面
在with代码块中,写的所有的SQL语句都属于同一个事务
"""
except Exception as e:
print(e)
try:
with transaction.atomic():
pass
# sql1
# sql2
"""
在with代码块中,写的所有的SQL语句都属于同一个事务
"""
except Exception as e:
print(e)
ORM建表参数补充
unique: 唯一
db_index: 添加索引
default: 默认值
to:要关联的表
to_field:指定关联的字段
db_constraint:不再创建外键约束
返回QuerySet对象的方法有
all()
filter()
exclude()
order_by()
reverse()
distinct()
特殊的QuerySet
values() 返回一个可迭代的字典序列
values_list() 返回一个可迭代的元祖序列
返回具体对象的
get()
first()
last()
返回布尔值的方法有:
exists()
返回数字的方法有
count()
choices参数
针对是可以列举完的数据,这种情况下一般使用choices字段参数。
例如:
gender:male,famale,other
学历:小学 A
初中 B
高中 C
专科 D
本科 E
研究生 F
那么我们在定义字段的时候就可以用到choices参数。
models.py
class User(modek.Model):
gender_choice = (
(1, 'male'),
(2, 'female'),
(3, 'others'),
) # 需要先定义一个元组
gender = models.IntegerField(choices=gender_choice)
取值的时候我们不能直接取,而是要用到固定句式
get_字段名_display()
res = models.User.objects.filter(pk=10).first()
print(res.get_gender_display())
多对多第三张表的三种创建方式
当我们使用ORM创建多对多的表关系的时候,其实是有三种创建方式的,这三种方式的优缺点各不相同。
全自动
即设置好外联字段的参数,利用ORM自动帮我们创建,它的优点是可以利用正反向查询的概念,还可以利用ORM给我们的内置方法add,set,remove,clear等,缺点是扩展性差不支持再创建其它字段了。
class Book(models.Model):
title = models.CharField(max_length=32)
price = models.DecimalField(max_digits=8, decimal_places=2)
author = models.ManyToManyField(to='Author')
class Author(models.Model):
name = models.CharField(max_length=32)
纯手动
class Book(models.Model):
title = models.CharField(max_length=32)
price = models.DecimalField(max_digits=8, decimal_places=2)
class Author(models.Model):
name = models.CharField(max_length=32)
class BookToAuthor(models.Model):
book_id = models.ForeignKey(to='Book')
author_id = models.ForeignKey(to='Author')
可以手动创建一张表对两个表的ID,特点是不可使用正反向查询的概念和ORM给我们的内置方法add,set,remove,clear等,但是扩张性比较好。
半自动
class Book(models.Model):
title = models.CharField(max_length=32)
price = models.DecimalField(max_digits=8, decimal_places=2)
authors = models.ManyToManyField(to='Author', through='Book2Author', through_fields=('book','author'))
# 指定一下哪张表为第三张表
# through_fields顺序,在哪张表写的就将那张表名写在前面
class Author(models.Model):
name = models.CharField(max_length=32)
class BookToAuthor(models.Model):
book_id = models.ForeignKey(to='Book')
author_id = models.ForeignKey(to='Author')
推荐用半自动方式,既可以扩展也可以使用正反向查询的概念,但内置方法不可以使用。