ORM 图书管理系统
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,
Max
,
Min
分组函数(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 图书管理系统的更多相关文章
- 在Django中使用ORM创建图书管理系统
一.ORM(对象关系映射) 很多语言的web框架中都有这个概念 1. 为什么要有ORM? 1. 写程序离不开数据,要使用数据就需要连接数据库,但是不同的数据库在sql语句上(mysql,oracle等 ...
- Django学习——图书管理系统图书修改、orm常用和非常用字段(了解)、 orm字段参数(了解)、字段关系(了解)、手动创建第三张表、Meta元信息、原生SQL、Django与ajax(入门)
1 图书管理系统图书修改 1.1 views 修改图书获取id的两种方案 1 <input type="hidden" name="id" value=& ...
- ORM练习项目-图书管理系统(BMS)实现细节
分析 一本书 可以由多个作者编著 一本书只能由一个出版社出版 一个作者可以写多本书 每个作者有自己的简介 对应关系: Author-Book # 多对多 Publish-Book # 一对多 Auth ...
- [入门级] 基于 visual studio 2010 mvc4 的图书管理系统开发初步 (二)
[入门级] 基于 visual studio 2010 mvc4 的图书管理系统开发初步 (二) Date 周六 10 一月 2015 By 钟谢伟 Category website develop ...
- Django练习——图书管理系统
Django图书管理系统 创建一个项目 1. django-admin startproject 图书管理 2. cmd 命令终端下创建一个app python manage.py startapp ...
- Django——图书管理系统
基于Django的图书管理系统 1.主体功能 1.列出图书列表.出版社列表.作者列表 2.点击作者,会列出其出版的图书列表 3.点击出版社,会列出旗下图书列表 4.可以创建.修改.删除 图书.作者.出 ...
- Django(图书管理系统1)
day63 内容回顾 1. 单表的增删改查 1. 删和改 1. GET请求 URL传值 1. 格式 ...
- 11 基于django的图书管理系统 多表
1.需求 作业需求:1.列出图书列表.出版社列表.作者列表2.点击作者,会列出其出版的图书列表3.点击出版社,会列出旗下图书列表4.可以创建.修改.删除 图书.作者.出版社 踩分点:1.满足需求1,2 ...
- Python高级进阶(二)Python框架之Django写图书管理系统(LMS)
正式写项目准备前的工作 Django是一个Web框架,我们使用它就是因为它能够把前后端解耦合而且能够与数据库建立ORM,这样,一个Python开发工程师只需要干自己开发的事情就可以了,而在使用之前就我 ...
随机推荐
- 用python实现一个计算器
import re def atom_cal(exp): # 计算乘除法 if '*' in exp: a,b = exp.split('*') return str(float(a) * float ...
- hadoop22---wait,notify
vv wait和notify,是要加syschronized的,是要获取锁的,wait是释放控制权,别的线程就可以执行了,notify和notifyall是通知其他线程执行.
- 【笔记】c++文件
1.文件. #include <iostream> #include <cstdio> #include <string> #include <cstring ...
- Python3:文件读写
Python3:文件读写 open f = open('filename','r') # 读模式 f = open('filename','w') # 写模式 f = open('filename', ...
- 20145109 《Java程序设计》第四周学习总结
20145109 <Java程序设计>第四周学习总结 教材学习内容总结 Chapter 6 Inheritance & Polymorphism What is Inheritan ...
- 总结一下TODO的用法
1.设置任务的标签 WINDOW->preference->java->complier->task tags加一个 DONE:NORMAL表示已经完成的任务2. java ...
- centos/linux扩容Swap分区
查看现在的swap容量 [root@node1 ~]# free -h total used free shared buff/cache available Mem: 15G 3.8G 2.1G 5 ...
- shell编程学习笔记之标准输入输出(read&echo)
2017-07-17 09:32:07 输入read: 用途: 从标准输入读取一行,或者从文件描述符FD(file descriptor)中读取一行,并且将其分割成字段. 用法: read [-ers ...
- idea通过springboot初始化器新建项目
1.通过初始化器新建项目,勾选后 对应生成的pom文件 以及生成的包路径 2.生成项目后点击稍后弹出的自动自动导入maven工程的改变,当pom中有依赖改变时会自动刷新导入依赖 3.删除自动生成项目的 ...
- quartz(7)-源码分析
定时器启动 上图通过spring加载quartz <bean id="scheduler" class="org.springframework.schedulin ...