django之ORM专项训练之图书信息系统 了不起的双下方法实战 和 分组 聚合 Q, F查询,有約束和無約束

时间:2022-08-31 21:43:10

图书信息系统

django之ORM专项训练之图书信息系统  了不起的双下方法实战  和 分组  聚合  Q, F查询,有約束和無約束

双下方法的使用情况:要查确定的某一个对象他的属性值时,

首先获得具体对象的方法是  get()   first()   last()   获得具体对象之后,在找他的外键的属性    get() fitst() last()等方法获得的具体对象.外键.all()

这就是获得具体对象在通过他的外键找到他外键的数据

方向查询的时候想要用set方法的时候要

.get(name="小仙女").book_set.all().values_list("title")   

表结构设计

django之ORM专项训练之图书信息系统  了不起的双下方法实战  和 分组  聚合  Q, F查询,有約束和無約束
# 书
class Book(models.Model):
title = models.CharField(max_length=32)
publish_date = models.DateField(auto_now_add=True)
price = models.DecimalField(max_digits=5, decimal_places=2)
# 创建外键,关联publish
publisher = models.ForeignKey(to="Publisher")
# 创建多对多关联author
author = models.ManyToManyField(to="Author") def __str__(self):
return self.title # 出版社
class Publisher(models.Model):
name = models.CharField(max_length=32)
city = models.CharField(max_length=32) def __str__(self):
return self.name # 作者
class Author(models.Model):
name = models.CharField(max_length=32)
age = models.IntegerField()
phone = models.IntegerField()
detail = models.OneToOneField(to="AuthorDetail") def __str__(self):
return self.name # 作者详情
class AuthorDetail(models.Model):
addr = models.CharField(max_length=64)
email = models.EmailField()
django之ORM专项训练之图书信息系统  了不起的双下方法实战  和 分组  聚合  Q, F查询,有約束和無約束

普通查询练习

查找所有书名里包含番茄的书
查找出版日期是2017年的书
查找出版日期是2017年的书名
查找价格大于10元的书
查找价格大于10元的书名和价格
查找memo字段是空的书

查找在北京的出版社
查找名字以沙河开头的出版社

查找作者名字里面带“小”字的作者
查找年龄大于30岁的作者
查找手机号是155开头的作者
查找手机号是155开头的作者的姓名和年龄

查找书名是“番茄物语”的书的出版社
查找书名是“番茄物语”的书的出版社所在的城市
查找书名是“番茄物语”的书的出版社的名称

查找书名是“番茄物语”的书的所有作者
查找书名是“番茄物语”的书的作者的年龄
查找书名是“番茄物语”的书的作者的手机号码

查找书名是“番茄物语”的书的作者的地址
查找书名是“番茄物语”的书的作者的邮箱

简单示例

单表查询

查询书名为番茄物语的书

>>> models.Book.objects.filter(title="番茄物语")
<QuerySet [<Book: 番茄物语>]>

一对多查询

查询id为1的书的出版社所在的城市

>>> models.Book.objects.get(id=1).publisher.city
'北京'

查询id为1的出版社的出版的所有书籍(反向查找)

>>> models.Publisher.objects.get(id=1).book_set.all()
<QuerySet [<Book: 番茄物语>, <Book: 香蕉物语>]>

一对一查询

查询小精灵作者的邮箱

>>> models.Author.objects.get(name="小精灵").detail.email
'1@1.com'

查询所有addr="快乐星球"的作者姓名

>>> author_details = models.AuthorDetail.objects.filter(addr="快乐星球")
>>> for obj in author_details:
... print(obj.author.name)
小仙女
小魔女

多对多查询

查询番茄物语所有作者的姓名和邮箱(正向查找)

django之ORM专项训练之图书信息系统  了不起的双下方法实战  和 分组  聚合  Q, F查询,有約束和無約束
>>> models.Book.objects.get(title="番茄物语").author.all()
<QuerySet [<Author: 小精灵>, <Author: 小仙女>]>
>>> for obj in author_list:
... print(obj.name, obj.detail.email)
...
小精灵 1@1.com
小仙女 2@2.com
django之ORM专项训练之图书信息系统  了不起的双下方法实战  和 分组  聚合  Q, F查询,有約束和無約束

查询小仙女出版的所有书籍

>>> models.Author.objects.get(name="小仙女").book_set.all()
<QuerySet [<Book: 番茄物语>, <Book: 橘子物语>]>

了不起的双下划线

django之ORM专项训练之图书信息系统  了不起的双下方法实战  和 分组  聚合  Q, F查询,有約束和無約束

查询沙河出版社出版的所有书籍的名称和价格

(正向查)

>>> models.Book.objects.filter(publisher__name="沙河出版社").values_list("title", "price") 关联的字段名__另一张表的字段名
这里跨表查询数据当作条件筛选,从而得到数据
<QuerySet [('番茄物语', Decimal('9.90')), ('香蕉物语', Decimal('9.90'))]>

反向查

>>> models.Publisher.objects.get(name="沙河出版社").book_set.all().values_list("title", "price")
<QuerySet [('番茄物语', Decimal('9.90')), ('香蕉物语', Decimal('9.90'))]>

双下划线反查

>>> models.Publisher.objects.filter(name="沙河出版社").values_list("book__title", "book__price")    只有QuerySet  对象有 .values()方法 
                          可以直接反向查数据如上用法直接得到上边 表名__属性名          即.get() .first() 取出的对对象不能用此方法
.values <QuerySet [('番茄物语', Decimal('9.90')), ('香蕉物语', Decimal('9.90'))]>

查询小仙女出版的所有书籍名称

正向查

>>> models.Book.objects.filter(author__name="小仙女").values_list("title")
<QuerySet [('番茄物语',), ('橘子物语',)]>

反向查

>>> models.Author.objects.get(name="小仙女").book_set.all().values_list("title")
<QuerySet [('番茄物语',), ('橘子物语',)]>

双下划线反查

>>> models.Author.objects.filter(name="小仙女").values_list("book__title")


<QuerySet [('番茄物语',), ('橘子物语',)]>        注意这句话就等价于上边的那句,book_set.all().values_list('title')

查询沙河出版社出版的书籍的书名和作者姓名

正向查

>>> models.Book.objects.filter(publisher__name="沙河出版社").values_list("title", "author__name")
<QuerySet [('番茄物语', '小精灵'), ('番茄物语', '小仙女'), ('香蕉物语', '小魔女')]>

反向查这是

>>> models.Publisher.objects.filter(name="沙河出版社").values_list("book__title", "book__author__name")
<QuerySet [('番茄物语', '小精灵'), ('番茄物语', '小仙女'), ('香蕉物语', '小魔女')]>
("book__title", "book__author__name")  这个用双下方法查询   
这里注意跨三表查询,因为publisher和author没有关系
 而book和author有关系,所以这里用 book__author(这个是book中的外键  叫author 通过他来关联 author表)__name 通过book与author相关联

结论,连表查询都是  表名__列名  

只要有外键关系  无论是正向还是反向都能使用双下方法连表查询

双下划线反向查

>>> models.Publisher.objects.get(name="沙河出版社").book_set.all().values_list("title", "author__name")
<QuerySet [('番茄物语', '小精灵'), ('番茄物语', '小仙女'), ('香蕉物语', '小魔女')]>

补充

查询memo为空的所有书

>>> models.Book.objects.filter(memo__isnull=True)

聚合查询和分组查询

聚合

django之ORM专项训练之图书信息系统  了不起的双下方法实战  和 分组  聚合  Q, F查询,有約束和無約束

aggregate()  聚合 QuerySet 的一个终止子句 意思是得到的不在是queryset对象了,意思是说,它返回一个包含一些键值对的字典。键的名称是聚合值的标识符,值是计算出来的聚合值。键的名称是按照字段和聚合函数的名称自动生成出来的。  queryset终止子句还有 count

这里和mysql中的聚合很相似   穿插着记忆就可以

示例:

>>> models.Book.objects.all().aggregate(Avg("price"))
{'price__avg': 13.233333}

如果你想要为聚合值指定一个名称,可以向聚合子句提供它。

>>> models.Book.objects.aggregate(average_price=Avg('price'))
{'average_price': 13.233333}

如果你希望生成不止一个聚合,你可以向aggregate()子句中添加另一个参数。所以,如果你也想知道所有图书价格的最大值和最小值,可以这样查询:

>>> models.Book.objects.all().aggregate(Avg("price"), Max("price"), Min("price"))
{'price__avg': 13.233333, 'price__max': Decimal('19.90'), 'price__min': Decimal('9.90')}

分组

为调用的QuerySet中每一个对象都生成一个独立的统计值

django之ORM专项训练之图书信息系统  了不起的双下方法实战  和 分组  聚合  Q, F查询,有約束和無約束

示例1:统计每一本书的作者个数

django之ORM专项训练之图书信息系统  了不起的双下方法实战  和 分组  聚合  Q, F查询,有約束和無約束
>>> book_list = models.Book.objects.all().annotate(author_num=Count("author"))这句话可以理解为按照book对象来分组,  然后统计每一组中的数量
>>> for obj in book_list:
... print(obj.author_num)
...
2
1
1
django之ORM专项训练之图书信息系统  了不起的双下方法实战  和 分组  聚合  Q, F查询,有約束和無約束

示例2:统计出每个出版社买的最便宜的书的价格

>>> publisher_list = models.Publisher.objects.annotate(min_price=Min("book__price"))  也可以这样写  直接 models.Publisher.objects.annotate(  )
>>> for obj in publisher_list:
... print(obj.min_price)
...
9.90
19.90

方法二:

>>> models.Book.objects.values("publisher__name").annotate(min_price=Min("price"))  
这里可以用连表查询publisher__name 以他作为分组的依据, 然后 找出每个出版社出的最便宜的书》》》》》

<QuerySet [{'publisher__name': '沙河出版社', 'min_price': Decimal('9.90')}, {'publisher__name': '人民出版社', 'min_price': Decimal('19.90')}]>
# python:2.7.9
# django:1.7.8 class MessageTab(models.Model):
msg_sn = models.CharField(max_lenth=20, verbose_name=u'编号')
msg_name = models.CharField(max_length=50, verbose_name=u'消息名称')
message_time = models.DateTimeField(verbose_name=u'消息出现时间')
msg_status = models.CharField(max_length=50, default='未处理', verbose_name=u'消息状态')
class Meta:
db_table = 'message_tab'
---------------------

如果在开发过程中,有这么一个需求:查询各个消息状态的数量。那么我们经常会使用filter(…).count(…)来进行查询。现在我们可以使用:

    msgS = MessageTab.objects.values_list('msg_status').annotate(Count('id'))

其中,id为数据库自动生成的自增字段。values_list的用法自行Google,或者print出来看一看。查看原生sql

print msgS.query

打印结果为

SELECT `message_tab`.`msg_status`, COUNT(`message_tab`.`id`) AS `id__count` FROM `message_tab` GROUP BY `message_tab`.`msg_status` ORDER BY NULL
---------------------

可见values_list中的内容作为分组依据,并和annotate中的字段共同组成返回展示的字段

示例3:统计不止一个作者的图书

>>> models.Book.objects.annotate(author_num=Count("author")).filter(author_num__gt=1)
<QuerySet [<Book: 番茄物语>]>

示例4:根据一本图书作者数量的多少对查询集 QuerySet进行排序

>>> models.Book.objects.annotate(author_num=Count("author")).order_by("author_num")
<QuerySet [<Book: 香蕉物语>, <Book: 橘子物语>, <Book: 番茄物语>]>

示例5:查询各个作者出的书的总价格

>>> models.Author.objects.annotate(sum_price=Sum("book__price")).values("name", "sum_price")
<QuerySet [{'name': '小精灵', 'sum_price': Decimal('9.90')}, {'name': '小仙女', 'sum_price': Decimal('29.80')}, {'name': '小魔女', 'sum_price': Decimal('9.90')}]>

F查询和Q查询

F查询

在上面所有的例子中,我们构造的过滤器都只是将字段值与某个常量做比较。如果我们要对两个字段的值做比较,那该怎么做呢?

Django 提供 F() 来做这样的比较。F() 的实例可以在查询中引用字段,来比较同一个 model 实例中两个不同字段的值。

示例1:

查询评论数大于收藏数的书籍

from django.db.models import F
models.Book.objects.filter(commnet_num__gt=F('keep_num'))

Django 支持 F() 对象之间以及 F() 对象和常数之间的加减乘除和取模的操作。

models.Book.objects.filter(commnet_num__lt=F('keep_num')*2)

修改操作也可以使用F函数,比如将每一本书的价格提高30元

models.Book.objects.all().update(price=F("price")+30)

引申:

如果要修改char字段咋办?

如:把所有书名后面加上(第一版)

>>> from django.db.models.functions import Concat
>>> from django.db.models import Value

>>> models.Book.objects.all().update(title=Concat(F("title"), Value("("), Value("第一版")(这里是用value将夹的字转换成一个值), Value(")")))

Q查询

filter() 等方法中的关键字参数查询都是一起进行“AND” 的。 如果你需要执行更复杂的查询(例如OR语句),你可以使用Q对象

示例1:

django之ORM专项训练之图书信息系统  了不起的双下方法实战  和 分组  聚合  Q, F查询,有約束和無約束

django之ORM专项训练之图书信息系统  了不起的双下方法实战  和 分组  聚合  Q, F查询,有約束和無約束

查询作者名是小仙女或小魔女的

models.Book.objects.filter(Q(authors__name="小仙女")|Q(authors__name="小魔女"))

你可以组合& 和|  操作符以及使用括号进行分组来编写任意复杂的Q 对象。同时,Q 对象可以使用~ 操作符取反,这允许组合正常的查询和取反(NOT) 查询。

示例:查询作者名字是小仙女并且不是2018年出版的书的书名。

>>> models.Book.objects.filter(Q(author__name="小仙女") & ~Q(publish_date__year=2018)).values_list("title")
<QuerySet [('番茄物语',)]>

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

例如:查询出版年份是2017或2018,书名中带物语的所有书

>>> models.Book.objects.filter(Q(publish_date__year=2018) | Q(publish_date__year=2017), title__icontains="物语")
<QuerySet [<Book: 番茄物语>, <Book: 香蕉物语>, <Book: 橘子物语>]>

約束

無約束

            class UserType(models.Model):
title = models.CharField(max_length=32) class UserInfo(models.Model):
name = models.CharField(max_length=32)
email = models.CharField(max_length=32)
# 无数据库约束,但可以进行链表
ut = models.ForeignKey(to='UserType',db_constraint=False)

有约束

            class UserType(models.Model):
title = models.CharField(max_length=32) class UserInfo(models.Model):
name = models.CharField(max_length=32)
email = models.CharField(max_length=32)
# 有数据库约束,可以进行链表
ut = models.ForeignKey(to='UserType')

django之ORM专项训练之图书信息系统 了不起的双下方法实战 和 分组 聚合 Q, F查询,有約束和無約束的更多相关文章

  1. Django---ORM的常用字段和自定义字段&comma;DjangoORM字段与数据库类型对应&comma;字段参数和Meta的参数&comma;Django的admin操作&comma;13中orm操作方法&comma;单标的双下方法

    Django---ORM的常用字段和自定义字段,DjangoORM字段与数据库类型对应,字段参数和Meta的参数,Django的admin操作,13中orm操作方法,单标的双下方法 一丶ORM常用字段 ...

  2. Python学习---ORM查询之基于对象的正向&sol;反向&sol;聚合&sol;分组&sol;Q&sol;F查询

    ORM查询之基于对象的正向查询与反向查询 对象形式的查询 # 正向查询 ret1=models.Book.objects.first() print(ret1.title) print(ret1.pr ...

  3. python自动化开发-&lbrack;第十八天&rsqb;-django的ORM补充与ajax&comma;分页器

    今日概要: 1.ORM一对多,多对多 2.正向查询,反向查询 3.聚合查询与分组查询 4.F查询和Q查询 5.ajax 6.分页器 一.ORM补充: django在终端打印sql语句设置: LOGGI ...

  4. Django之ORM数据库

    5.1 数据库的配置 1    django默认支持sqlite,mysql, oracle,postgresql数据库.  <1> sqlite django默认使用sqlite的数据库 ...

  5. 九、Django之ORM

    一.ORM概述 用于实现面向对象编程语言里不同类型系统的数据之间的转换,换言之,就是用面向对象的方式去操作数据库的创建表以及增删改查等操作. 到目前为止,当我们的程序涉及到数据库相关操作时,一般操作流 ...

  6. Django ORM字段类型 单表增删改查 万能的双下划线

    1.ORM三种模型 模型之间的三种关系:一对一,一对多,多对多. 一对一:实质就是在主外键(author_id就是foreign key)的关系基础上,给外键加了一个UNIQUE=True的属性: 一 ...

  7. django【orm操作】

    一.ORM表结构 class Publisher(models.Model): name = models.CharField(max_length=30, verbose_name="名称 ...

  8. django(七)之数据库表的单表-增删改查QuerySet,双下划线

    https://www.cnblogs.com/haiyan123/p/7738435.html https://www.cnblogs.com/yuanchenqi/articles/6083427 ...

  9. Python学习(三十五)—— Django之ORM训练专题

    图书管理系统 一.表结构设计 # 书 class Book(models.Model): title = models.CharField(max_length=32) publish_date = ...

随机推荐

  1. 【LeetCode】Sort Colors

    Sort Colors Given an array with n objects colored red, white or blue, sort them so that objects of t ...

  2. wikioi 1205 单词倒排

    /*====================================================================== 1205 单词翻转 题目描述 Description ...

  3. 如何使用gcc编译器

    开始... 首先,我们应该知道如何调用编译器.实际上,这很简单.我们将从那个著名的第一个C程序开始. #include <stdio.h> int main() { printf(&quo ...

  4. Docker安装应用程序&lpar;Centos6&period;5&lowbar;x64&rpar;

    Docker安装应用程序(Centos6.5_x64) Authoer::jom_ch@2014/7/23 Docker官方网站 http://www.docker.com/ 一,安装EPEL 关于E ...

  5. 嵌入式ARM开发环境搭建

    1. 安装,配置,启动FTP服务 安装FTP: sudo apt-get install vsftpd 修改vsftpd的配置文件/etc/vsftpd.conf,将下面两行的'#'去掉#local_ ...

  6. Java 第九周总结

    1. 本周学习总结 2. 书面作业 1.常用异常 1.1 截图你的提交结果(出现学号) 1.2 自己以前编写的代码中经常出现什么异常.需要捕获吗(为什么)?应如何避免? 以前的代码经常出现空指针的,需 ...

  7. 『练手』通过注册表 获取 VS 和 SQLServer 文件路径

    获取任意 VS 和 SQLServer 的 磁盘安装目录. 背景需求:如果磁盘电脑安装了 VS 或者 SQLServer 则 认定这台计算机 的使用者 是一名 软件研发人员,则让程序 以最高权限运行. ...

  8. 【JMeter】(1&rpar;---入门

    JMeter入门 https://www.cnblogs.com/qdhxhz/p/9222105.html 一.概述 JMeter是Apache下一款在国外非常流行和受欢迎的开源性能测试工具,JMe ...

  9. 如何使用&commat;vue&sol;cli 3&period;0在npm上创建,发布和使用你自己的Vue&period;js组件库

    译者按: 你可能npm人家的包过成千上万次,但你是否有创建,发布和使用过自己的npm包? 原文: How to create, publish and use your own VueJS Compo ...

  10. 从零开始学Shell&lpar;一&rpar;

    1.$表示普通用户,#表示超级用户.2.sh /home/path/script.sh3.chmod a+x script.sh  增加可执行权限    ./script.sh    #./表示当前的 ...