摘要:

  • F查询
  • Q查询
  • 事务

一、F查询

  • 在上面所有的例子中,我们构造的过滤器都只是将字段值与某个我们自己设定的常量做比较。如果我们要对两个字段的值做比较,那该怎么做呢?
    Django 提供 F() 来做这样的比较。F() 的实例可以在查询中引用字段,来比较同一个 model 实例中两个不同字段的值。
    示例:
    建表:

    1. from django.db import models
    2.  
    3. class Goods(models.Model):
    4. name = models.CharField(max_length=32)
    5. price = models.DecimalField(max_digits=8, decimal_places=2)
    6. remain = models.BigIntegerField()
    7. sold_out = models.BigIntegerField()

    插入模块

    1. from django.db.models import F,Q

    例子:查询卖出数量大于库存数的商品名称

    1. res = models.Goods.objects.filter(sold_out__gt=F('remain')).values_list('name', 'sold_out', 'remain')
    2. print(res)
    3. # <QuerySet [('袜子', 600, 100), ('夹克', 20, 10)]>

    F可以帮我们取到表中某个字段对应的值来当作我的筛选条件,而不是我认为自定义常量的条件了,实现了动态比较的效果

    Django 支持 F() 对象之间以及 F() 对象和常数之间的加减乘除和取模的操作。基于此可以对表中的数值类型进行数学运算
    例子:将每个商品的价格提高50块

    1. res1 = models.Goods.objects.update(price=F('price')+100)

    引申:如何修改char字段,比如将上面的表中商品名称全部尾部加上‘清仓’两个字,如何操作?
    这里需要使用2个模块:Concat 和 Value

    1. from django.db.models.functions import Concat
    2. from django.db.models import Value
    3.  
    4. res = models.Goods.objects.update(name=Concat(F('name'), Value('清仓')))

    Concat表示进行字符串的拼接操作,参数位置决定了拼接是在头部拼接还是尾部拼接,Value里面是要新增的拼接值

二、 Q查询

  • filter()方法汇总的逗号get的条件是与的关系,如果要执行更复杂的查询,比如or的语句,就会用到Q对象
    例子:
    查询卖出数量大于100或者价格小于300的商品名

    1. from django.db.models import F,Q
    2.  
    3. res = models.Goods.objects.filter(Q(sold_out__gt=100)|Q(price__lt=300)).values_list('name', 'sold_out', 'price')
    4. print(res)
    5.  
    6. <QuerySet [('袜子清仓', 600, Decimal('129.90')), ('寸衫清仓', 10, Decimal('229.90'))]>

    对条件包裹一层Q时候,filter即可支持交叉并的比较符

    1. # 查询库存数是小于等于20,且卖出数不是10的产品
    2. res = models.Goods.objects.filter(Q(remain__lte=20)&~Q(sold_out=12)).values_list('name')

    我们可以组合& 和|  操作符以及使用括号进行分组来编写任意复杂的Q 对象。

    同时,Q 对象可以使用~ 操作符取反,这允许组合正常的查询和取反(NOT) 查询。

    1. # 查询产品名包含新款或者爆款,且库存大于60的产品
    2.  
    3. res = models.Goods.objects.filter(Q(name__contains='新款')|Q(name__contains='爆款'), remain__gt=60).values_list('name')

    查询函数可以混合使用Q 对象和关键字参数。所有提供给查询函数的参数(关键字参数或Q 对象)都将"AND”在一起。但是,如果出现Q 对象,它必须位于所有关键字参数的前面

  • 重点使用方法补充:
    1. 实例化Q对象:q = Q()
    2. q.connector = 'or' # 默认q之间的条件都是与关系,这里改成or关系
    3. q.children.append(('name','sgt')) # 插入第一个条件,注意这里传的是一个元祖
    4. q.children.append(('password','')) # 可以继续插入条件
    5. # q对象支持直接放入filter括号内,它们之间默认是and关系,可以通过上面的q.connect = 'or'来修改成或关系
    6. models.User.objects.filter(q) # 这里面就是查询的条件们,它们之间默认是与关系,可以修改成or关系

三、事务

  • 定义:将多个sql语句操作变成原子性操作,要么同时成功,有一个失败在里面就回滚到原来的状态,保证数据的完整性和一致性(NoSQL数据库对事务则是部分支持)

    1. # 事务
    2. # 购买商品
    3. # 产品表中修改数据:卖出数+1,库存-1
    4. from django.db.models import F
    5. from django.db import transaction
    6. try :
    7. with transaction.atomic():
    8. models.Goods.objects.filter(id=1).update(remain=F('remain')-1, sold_out=F('sold_out')+1)
    9. except Exception as e:
    10. print(e)

四、补充的一些常用的操作

  • update()与save()的区别

    两者都是对数据的修改保存操作,但是save()函数是将数据列的全部数据项全部重新写一遍,而update()则是针对修改的项进行针对的更新效率高耗时少

    所以以后对数据的修改保存用update()

  • 让我们通过orm对数据库操作时候,让终端显示内部查询操作sql语句:
    在Django项目的settings.py文件中,在最后复制粘贴如下代码:
    1. LOGGING = {
    2. 'version': 1,
    3. 'disable_existing_loggers': False,
    4. 'handlers': {
    5. 'console':{
    6. 'level':'DEBUG',
    7. 'class':'logging.StreamHandler',
    8. },
    9. },
    10. 'loggers': {
    11. 'django.db.backends': {
    12. 'handlers': ['console'],
    13. 'propagate': True,
    14. 'level':'DEBUG',
    15. },
    16. }
    17. }

    配置好之后,再执行任何对数据库进行操作的语句时,会自动将Django执行的sql语句打印到pycharm终端上
    补充:
    除了配置外,还可以通过一点query即可查看查询语句,具体操作如下:

  • only 与 defer
    拿到的是一个对象  两者是相反的
    (前提设置:设置每次操作数据库时候都会有sql语句现实在pycharm终端,上面已说明步骤)
    先看看only:

    看看defer

  • choice属性
    choice这个属性,用来限制用户做出选择的范围。比如说性别的选择(男或女)
    1. class MyUser(models.Model):
    2. name = models.CharField(max_length=32)
    3. password = models.CharField(max_length=32)
    4. choices = ((1, '男'), (2, '女'), (3, '其它'))
    5. gender = models.CharField(choices=choices, default=1, max_length=5)

    choice接收一个元组(保证值不可变),同理每一个选项也是由一个元组(value,display_name)构成。显而易见,display_name就是要在页面中展示的。

    如何取到value和displayname?

    比如说实例一个User对象user_obj,
    user_obj.gender = value  (通过属性取value)
    user_obj.get_gender_display() = display_name  (通过 get_属性_display()方法取display_name)

    在模板中可以通过模板语言{{ user_obj.gender }}很简单地显示value,但不能直接调用get属性_display方法(模板毕竟是模板语言),要解决这个问题,可以用自定义过滤器来搞定:
    来回顾一下如何自定义过滤器:
    1,在应用名下新建一个名为templatetags文件夹
    2,在该文件夹内新建一个py文件,名字随意
    3,在该py文件内添加固定代码和自定义过滤器代码

    1. from django import template
    2.  
    3. register = template.Library()
    4.  
    5. @register.filter(name='displayName')
    6. def displayName(obj):
    7. res = obj.get_gender_display
    8. return res()
    9.  
    10. # 视图层:
    11. from django.shortcuts import render, HttpResponse,reverse
    12. # Create your views here.
    13. from app01 import models
    14. def index(request):
    15. obj = models.MyUser.objects.filter(pk=1).first()
    16. return render(request, 'index.html', locals())
    17.  
    18. # 前端(html页面):
    19. {% load my_file %}
    20. {{ obj|displayName}}
  • bulk_create批量插入数据
    当我们使用orm来一次性新增很多表记录的时候,等待结果的时间会非常的慢,如果一次性需要批量插入很多数据的时候就需要使用bulk_create来批量插入数据
    1. import random
    2.  
    3. user_list = ['用户[{}]'.format(i) for i in range(100)]
    4. data = []
    5. for j in user_list:
    6. data.append(models.MyUser(name=j, password='', gender=str(random.choice([1, 2, 3]))))
    7. models.MyUser.objects.bulk_create(data)
  • select_related和prefetch_related
    1. def select_related(self, *fields)
    2. 性能相关:表之间进行join连表操作,一次性获取关联的数据。
    3.  
    4. 总结:
    5. 1. select_related主要针一对一和多对一关系进行优化。
    6. 2. select_related使用SQLJOIN语句进行优化,通过减少SQL查询的次数来进行优化、提高性能。
    7.  
    8. def prefetch_related(self, *lookups)
    9. 性能相关:多表连表操作时速度会慢,使用其执行多次SQL查询在Python代码中实现连表操作。
    10.  
    11. 总结:
    12. 1. 对于多对多字段(ManyToManyField)和一对多字段,可以使用prefetch_related()来进行优化。
    13. 2. prefetch_related()的优化方式是分别查询每个表,然后用Python处理他们之间的关系。

Web框架之Django_06 模型层了解(F查询、Q查询、事务、update和save、only和defer、choice属性、bulk_create)的更多相关文章

  1. Web框架之Django_05 模型层了解(单表查询、多表查询、聚合查询、分组查询)

    摘要: 单表查询 多表查询 聚合查询 分组查询 一.Django ORM 常用字段和参数: 常用字段:#AutoFieldint自增列,必须填入参数primary_key = True,当model中 ...

  2. web框架开发-Django模型层(2)-多表操作

    很重要,都是精华 多表关系模型 一对一 一旦确定表关系是一对一,在两张表中的任意一张表中建立关联字段+Unique 一对多 一旦确定表关系是一对多,创建关联字段在多的表中 多对多 一旦确定表关系是多对 ...

  3. web框架开发-Django模型层(1)之ORM简介和单表操作

    ORM简介 不需要使用pymysql的硬编码方式,在py文件中写sql语句,提供更简便,更上层的接口,数据迁移方便(有转换的引擎,方便迁移到不同的数据库平台)…(很多优点),缺点,因为多了转换环节,效 ...

  4. (21)模型层 -ORM之msql 聚合查询,F和Q(与、或、非查询)、分组查询

    什么是聚合查询,就是使用聚合函数做计算 from django.db.models import Count,Avg,Max,Min   #聚合函数要从模块中导入 from django.db.mod ...

  5. Django 08 Django模型基础3(关系表的数据操作、表关联对象的访问、多表查询、聚合、分组、F、Q查询)

    Django 08 Django模型基础3(关系表的数据操作.表关联对象的访问.多表查询.聚合.分组.F.Q查询) 一.关系表的数据操作 #为了能方便学习,我们进入项目的idle中去执行我们的操作,通 ...

  6. Django中多表的增删改查操作及聚合查询、F、Q查询

    一.创建表 创建四个表:书籍,出版社,作者,作者详细信息 四个表之间关系:书籍和作者多对多,作者和作者详细信息一对一,出版社和书籍一对多 创建一对一的关系:OneToOne("要绑定关系的表 ...

  7. django F与Q查询 事务 only与defer

    F与Q 查询 class Product(models.Model): name = models.CharField(max_length=32) #都是类实例化出来的对象 price = mode ...

  8. Django 聚合查询 分组查询 F与Q查询

    一.聚合查询 需要导入模块:from django.db.models import Max, Min, Sum, Count, Avg 关键语法:aggregate(聚合结果别名 = 聚合函数(参数 ...

  9. Django 聚合分组F与Q查询及choices

    一.聚合查询 需要导入模块:from django.db.models import Max, Min, Sum, Count, Avg 关键语法:aggregate(聚合结果别名 = 聚合函数(参数 ...

随机推荐

  1. Linux | C代码的编写、运行和调试

    1.  建立.c文件 在终端下输入:vi mytest.c [使用编辑器 vim] 键入键盘i键,使vi编辑器进入编辑模式 接下来在vi编译器中编写代码,如: #include <stdio.h ...

  2. IP服务-6-SNMP

    SNMP(简单网络管理协议) SNMP更为正式的说法是互联网标准管理框架(Internet Standard Management Framework).在这个协议架构中.被管理的设备(SNMP代理) ...

  3. 牛客寒假6-C.项链

    链接:https://ac.nowcoder.com/acm/contest/332/C 题意: 小B想给她的新项链染色. 现在有m种颜色,对于第i种颜色,小B有a_i单位的颜料,每单位颜料可以染项链 ...

  4. mac下启动lnmp的方式

    mac air 系列由于各种原因使得我不得不重启,重启后发现lnmp全部都关闭了, nginx: sudo nginx   php-fpm: sudo php-fpm mysql: cd /usr/l ...

  5. 自己写的Grid组件,第二版

    大体没什么变化,主要是添加了一个方法,getSelectedItems(),返回当前选中的数据项. (function ($) { $.fn.GridView = function (setting) ...

  6. 11.JAVA-Object类之finalize(),clone(),toString()等方法覆写

    1.Object介绍 Object类是一个特殊的类,是所有类(包括数组,接口 )的父类,如果一个类没有用extends明确指出继承于某个类,那么它默认继承Object类,所以可以通过向上转型的方法使用 ...

  7. Android Studio报错Unable to resolve dependency for ':app@release/compileClasspath':无法引用任何外部依赖的解决办法

    Android Studio 在引用外部依赖时,发现一直无法引用外部依赖.刚开始以为是墙的问题,尝试修改Gradle配置,未解决问题. 最终发现原来是在Android Sudio安装优化配置时,将Gr ...

  8. 实训随笔:EL表达式JSON应用

    由于之前在学校写的jsp页面都是夹杂着java代码的,所以之前写了个jsp,满满的<%%>和java代码,老师说那样太不美观了啊!!!要全部用EL表达式替代了.本人还是太笨了,弄了一上午才 ...

  9. python 基础网络编程1

    python 基础网络编程1 Source code: Lib/socketserver.py lib的主目录下有一个sockserver.py文件, 里面是python基本的网络编程模型 共有一个b ...

  10. nginx “403 Forbidden” 错误 解决方法

    错误的原因是缺少index.html或者index.php文件,就是配置文件中index index.html index.htm这行中的指定的文件 只需要配置时加一句  index  index.h ...