F与Q查询 事务 choices参数

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')

推荐用半自动方式,既可以扩展也可以使用正反向查询的概念,但内置方法不可以使用。

上一篇:《深入理解Spark:核心思想与源码分析》正式出版上市


下一篇:.net core系列之初识asp.net core