models.py(模型)

from django.db import models

# Create your models here.

# 书   出版社  作者   作者详情表

#  书
class Book(models.Model):
title = models.CharField(max_length=32) # 书名
price = models.DecimalField(max_digits=5,decimal_places=2) # 五位数字,两位小数 999.99
publish_date = models.DateField(auto_now_add=True)
# auto_now = True 每一次修改都自动更新时间; auto_now_add=True 第一次创建时自动填写时间
memo = models.CharField(max_length=128) def __str__(self):
return self.title # 出版社
class Publisher(models.Model):
name = models.CharField(max_length=32)
addr = models.CharField(max_length=128)
phone = models.IntegerField() def __str__(self):
return self.name # 作者表
class Author(models.Model):
name = models.CharField(max_length=16)
# 作者和作者详情表表示一对一关联的
detail = models.OneToOneField(to="AuthorDetail") # 作者和书的关系是多对多
books = models.ManyToManyField(to="Book") def __str__(self):
return self.name # 作者详情表
class AuthorDetail(models.Model):
city = models.CharField(max_length=32)
email = models.EmailField()

加数据

关于单表查询

>>>  找书名含有“看见”的书(contains-->包含)
>>> models.Book.objects.filter(title__contains="看")
--- <QuerySet [<Book: 看见>]> # 查找出版日期是2017年的书
>>> models.Book.objects.filter(publish_date__year="")
--- <QuerySet [<Book: 好吗,好的>, <Book: 看见>]> # 查找出版日期大于2017年的书
>>> models.Book.objects.filter(publish_date__year__gt="")
-- <QuerySet [<Book: 用我一辈子去忘记>, <Book: 镜子中的世界>]> # 查找出版日期是2017年的书名
>>> models.Book.objects.filter(publish_date__year="").values("title")
--- <QuerySet [{'title': '好吗,好的'}, {'title': '看见'}]> # 查找价格大于10元的书名和价格
>>> models.Book.objects.filter(price__gt="").values("title","price")
--- <QuerySet [{'title': '看见', 'price': Decimal('10.90')},
    {'title': '用我一辈子去忘记', 'price': Decimal('15.90')},
    {'title': '天空之城', 'price': Decimal('20.90')}]> # 查找memo为空的书
>>> models.Book.objects.filter(memo__isnull=True)
--- <QuerySet []>
# 查询在北京的出版社
>>> models.Publisher.objects.filter(addr="北京")
--- <QuerySet [<Publisher: 天天>]>
# 查找出版社名字以“天”开头的出版社
>>> models.Publisher.objects.filter(name__startswith="天")
--- <QuerySet [<Publisher: 天天>, <Publisher: 天空之境>]>
>>>  a = models.Book.objects.filter(price__gt="").values("title","price")
>>> for i in a:
... print(i,type(i)) {'title': '看见', 'price': Decimal('10.90')} <class 'dict'>
{'title': '用我一辈子去忘记', 'price': Decimal('15.90')} <class 'dict'>
{'title': '天空之城', 'price': Decimal('20.90')} <class 'dict'> >>> for i in a:
... print(i["price"])
10.90
15.90
20.90

多对多

查询规律(正向,用字段。  反向,用表名)

                   .authors.all()
(Book------------(查所有相关的作者)--------------->Author)
<--------(查作者写过所有相关的书籍)------------
.book_set.all()
#  查找书名为"看见"的书
>>> models.Book.objects.filter(title="看见")
-- <QuerySet [<Book: 看见>]>
# 此时找到的是一个对象集合 >>> models.Book.objects.get(title="看见")
--- <Book: 看见>
# 此时找到的是书的对象() >>> models.Book.objects.get(title="看见").publisher
--- <Publisher: 稻城出版社> # 对应的是一个出版社的对象 >>> models.Book.objects.get(title="看见").publisher.name
--- '稻城出版社' # 查找书名为“看见”的出版社的地址
>>> models.Book.objects.get(title="看见").publisher.addr
--- '云南' (多对多反向查找)表名_set # 查找书名为“看见”的所有作者
# 从书找作者为反向查找 表名_set >>> models.Book.objects.get(title="看见").author_set.all()
--- <QuerySet [<Author: 柴静>, <Author: 小黑>, <Author: 小景>]> # 查找书名为“看见”的所有作者的名字
# 不能直接.name,QuerySet没有这个方法 >>> models.Book.objects.get(title="看见").author_set.all().values("name")
---- <QuerySet [{'name': '柴静'}, {'name': '小黑'}, {'name': '小景'}]> # 查找书名是“看见”的作者的邮箱
# detail是作者与作者详情表一对一关联的
# 双下划线表示跨表 >>> models.Book.objects.get(title="看见").author_set.all().values("detail__email") -- <QuerySet [{'detail__email': '11@66'}, {'detail__email': '11@88'}, {'detail__email': '11@99'}]> # 查找作者为“柴静”的所有书 (正向找) 直接用字段名(books)
# .books 相当于Django帮你去查询多对多关联的表
>>> models.Author.objects.get(name="柴静").books.all()
--- <QuerySet [<Book: 看见>, <Book: 用我一辈子去忘记>]>
外键的反向查询

>>> models.Publisher.objects.get(name="天天出版社").book_set.all()
--- <QuerySet [<Book: 用我一辈子去忘记>, <Book: 天空之城>]> >>> models.Publisher.objects.get(name="天天出版社").book_set.all().values_list("title","price")
--- <QuerySet [('用我一辈子去忘记', Decimal('15.90')), ('天空之城', Decimal('20.90'))]> >>> models.Book.objects.filter(publisher__name="天天出版社").values_list("title","price")
---- <QuerySet [('用我一辈子去忘记', Decimal('15.90')), ('天空之城', Decimal('20.90'))]> # 由作者找到书
# l两种查法,查找柴静出版的书的书名及价格
>>> models.Author.objects.get(name="柴静").books.all().values_list("title","price")
--- <QuerySet [('看见', Decimal('10.90')), ('用我一辈子去忘记', Decimal('15.90'))]> >>> models.Author.objects.filter(name="柴静").values_list("books__title","books__price")
--- <QuerySet [('看见', Decimal('10.90')), ('用我一辈子去忘记', Decimal('15.90'))]> # 使用filter得到的是QuerySet .对象列表
values_list是query set的方法 get得到的是具体数据对象
对象才能直接.
# 查找书名为"围城"的作者,写过的书
>>> author_objs = models.Author.objects.filter(books__title="围城")
>>> for i in author_objs
... print(i.books.all())
<QuerySet [<Book: 镜子中的世界>, <Book: 围城>]>
<QuerySet [<Book: 用我一辈子去忘记>, <Book: 围城>]>

总结:在上述的论述中,所有的反向的查询的表名均为小写,且需要提醒的是在一对一的反向查询中表名不需要跟set,因为它只有一个对象,通过“.表名”得到的是一个models对象,可以直接查询需要的字段。

聚合函数

aggregate()QuerySet 的一个终止子句,意思是说,它返回一个包含一些键值对的字典。键的名称是聚合值的标识符,值是计算出来的聚合值。键的名称是按照字段和聚合函数的名称自动生成出来的。如果你想要为聚合值指定一个名称,可以向聚合子句提供它。如下例:

#查询所有书籍的平均价格
# 实例1:
a = models.Book.objects.all().aggregate(Avg("price"))
print(a)
# {'price__avg': 12.066667}
# 实例2:
a = models.Book.objects.all().aggregate(avgprice=Avg("price"))
print(a)
# {'avgprice': 12.066667}

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

# 查询所有书籍的平均价格、价格最大小值、价格最大值
a = models.Book.objects.all().aggregate(Avg("price"),Min("price"),Max("price"))
print(a) -- {'price__avg': 12.066667, 'price__min': Decimal('6.90'), 'price__max': Decimal('20.90')}

以上实例中需要按照如下方式引入相应的模块方法: from django.db.models import Avg, MaxMin

分组函数(annotate)

  annotate()为调用的QuerySet中每一个对象都生成一个独立的统计值(统计方法用聚合函数)。

  实例1:查询每一个出版社出版过的书籍个数

from django.db.models import Avg,Max,Min,Count
a = models.Publisher.objects.all().annotate(num=Count("book__title"))
#可以理解为每一个出版社对象增加一个num字段,该字段值是通过聚合函数联表求得
for i in a:
    print(i.num)
2
2
1
1

  annotate的返回值是querySet,如果不想遍历对象,可以用上values_list,如下:

a = models.Publisher.objects.all().annotate(num=Count("book__title")).values_list("name","num")
print(a) <QuerySet [('稻城出版社', 2), ('天天出版社', 2), ('天空之境出版社', 1), ('五道口出版社', 1)]>

查询每本书的作者个数

a = models.Book.objects.all().annotate(counts=Count("author__id")).values("title","counts")

-- <QuerySet [{'title': '好吗,好的', 'counts': 1}, 
{'title': '看见', 'counts': 3},
{'title': '用我一辈子去忘记', 'counts': 2},
{'title': '镜子中的世界', 'counts': 3},
{'title': '围城', 'counts': 2},
{'title': '天空之城', 'counts': 2}]>

F查询与Q查询

F查询

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

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

使用命令建app
E:\Django项目\Books>python3 manage.py startapp app02

注册:

#  当你的表里面有2个字段做比较,就用F查询

查找商品的收藏数大于购买数的商品
>>> models.Goods.objects.all().filter(keep_num__gt=F("buy_num"))
--- <QuerySet [<Goods: 娃哈哈>]> # 收藏数比购买数大2倍
>>> models.Goods.objects.all().filter(keep_num__gt=F("buy_num")*2)
--- <QuerySet [<Goods: 小天使>]>
# 将全部购买数增加100
>>> models.Goods.objects.all().update(buy_num=F("buy_num")+100)
5

引申:

如果需要修改char字段?

如:把所有商品名前面加上“你好”

from django.db.models import Value as V
from django.db.models.functions import Concat
models.Goods.objects.all().update(name=Concat(V("你好"),F("name")))

>>> 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(")")))

Q查询

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

示例一:

查询作者名是柴静为lishi

app01_models.Author.objects.filter(Q(name="柴静")|Q(name="jassin"))
<QuerySet [<Author: 柴静>, <Author: jassin>]>

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

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

from django.db.models import Q
from app01 import models as app01_models
models.Book.objects.filter(Q(author__name="柴静")&Q(publish_day__year=""))

查询函数可以混合使用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: 橘子物语>]>

ORM 图书管理系统的更多相关文章

  1. 在Django中使用ORM创建图书管理系统

    一.ORM(对象关系映射) 很多语言的web框架中都有这个概念 1. 为什么要有ORM? 1. 写程序离不开数据,要使用数据就需要连接数据库,但是不同的数据库在sql语句上(mysql,oracle等 ...

  2. Django学习——图书管理系统图书修改、orm常用和非常用字段(了解)、 orm字段参数(了解)、字段关系(了解)、手动创建第三张表、Meta元信息、原生SQL、Django与ajax(入门)

    1 图书管理系统图书修改 1.1 views 修改图书获取id的两种方案 1 <input type="hidden" name="id" value=& ...

  3. ORM练习项目-图书管理系统(BMS)实现细节

    分析 一本书 可以由多个作者编著 一本书只能由一个出版社出版 一个作者可以写多本书 每个作者有自己的简介 对应关系: Author-Book # 多对多 Publish-Book # 一对多 Auth ...

  4. [入门级] 基于 visual studio 2010 mvc4 的图书管理系统开发初步 (二)

    [入门级] 基于 visual studio 2010 mvc4 的图书管理系统开发初步 (二) Date  周六 10 一月 2015 By 钟谢伟 Category website develop ...

  5. Django练习——图书管理系统

    Django图书管理系统 创建一个项目 1. django-admin startproject 图书管理 2. cmd 命令终端下创建一个app python manage.py startapp ...

  6. Django——图书管理系统

    基于Django的图书管理系统 1.主体功能 1.列出图书列表.出版社列表.作者列表 2.点击作者,会列出其出版的图书列表 3.点击出版社,会列出旗下图书列表 4.可以创建.修改.删除 图书.作者.出 ...

  7. Django(图书管理系统1)

    day63 内容回顾     1. 单表的增删改查         1. 删和改             1. GET请求 URL传值                 1. 格式            ...

  8. 11 基于django的图书管理系统 多表

    1.需求 作业需求:1.列出图书列表.出版社列表.作者列表2.点击作者,会列出其出版的图书列表3.点击出版社,会列出旗下图书列表4.可以创建.修改.删除 图书.作者.出版社 踩分点:1.满足需求1,2 ...

  9. Python高级进阶(二)Python框架之Django写图书管理系统(LMS)

    正式写项目准备前的工作 Django是一个Web框架,我们使用它就是因为它能够把前后端解耦合而且能够与数据库建立ORM,这样,一个Python开发工程师只需要干自己开发的事情就可以了,而在使用之前就我 ...

随机推荐

  1. TP框架基础2

    ---恢复内容开始--- [空操作和空控制器处理] 空操作:就没有指定的操作方法 空控制器:没有指定控制器 http://网址/index.php/Home/User/login http://网址/ ...

  2. angularjs 的controller的三种写法

    AngularJS 的controller其实就是一个方法,它有三种写法: 第一种: <pre name="code" class="javascript" ...

  3. LVS原理详解以及部署

    linux virtual server简称LVS,Internet的快速增长使多媒体网络服务器面对的访问数量快速增加,服务器需要具备提供大量并发访问服务的能力,因此对于大负载的服务器来讲, CPU. ...

  4. linux mkisofs(genisoimage)命令用法

    功能说明:建立ISO 9660映像文件. 常用命令:genisoimage -o imagename.iso file 语 法:mkisofs [-adDfhJlLNrRTvz][-print-siz ...

  5. Python3:Django连接Mysql数据库时出错,'Did you install mysqlclient or MySQL-python?'

    Python3:Django连接Mysql数据库时出错,'Did you install mysqlclient or MySQL-python?' 一.原因 因为Python版本问题,MySQLdb ...

  6. Hibernate 菜鸟教程 异常 集锦

    异常1.Error parsing JNDI name [foo] 异常信息摘要: org.hibernate.engine.jndi.JndiException: Error parsing JND ...

  7. docker 使用mysql

    mysql 5.7安装成功了,之前5.6一直报错不知道为什么 sudo docker run --name emall_mysql -e MYSQL_ROOT_PASSWORD=jbt1234 -e ...

  8. 谷歌浏览器安装vuejs devtools 插件

    1 . 下载chrome扩展插件. 在github上下载压缩包并解压到本地,github下载地址:https://github.com/vuejs/vue-devtools 2. npm instal ...

  9. js进阶---12-10、jquery绑定事件和解绑事件是什么

    js进阶---12-10.jquery绑定事件和解绑事件是什么 一.总结 一句话总结:on和off. 1.jquery如何给元素绑定事件? on方法 22 $('#btn1').on('click', ...

  10. python运行httpserver

    $ python -m SimpleHTTPServer $ python3 -m http.server