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. 用python实现一个计算器

    import re def atom_cal(exp): # 计算乘除法 if '*' in exp: a,b = exp.split('*') return str(float(a) * float ...

  2. hadoop22---wait,notify

    vv wait和notify,是要加syschronized的,是要获取锁的,wait是释放控制权,别的线程就可以执行了,notify和notifyall是通知其他线程执行.

  3. 【笔记】c++文件

    1.文件. #include <iostream> #include <cstdio> #include <string> #include <cstring ...

  4. Python3:文件读写

    Python3:文件读写 open f = open('filename','r') # 读模式 f = open('filename','w') # 写模式 f = open('filename', ...

  5. 20145109 《Java程序设计》第四周学习总结

    20145109 <Java程序设计>第四周学习总结 教材学习内容总结 Chapter 6 Inheritance & Polymorphism What is Inheritan ...

  6. 总结一下TODO的用法

      1.设置任务的标签 WINDOW->preference->java->complier->task tags加一个 DONE:NORMAL表示已经完成的任务2. java ...

  7. centos/linux扩容Swap分区

    查看现在的swap容量 [root@node1 ~]# free -h total used free shared buff/cache available Mem: 15G 3.8G 2.1G 5 ...

  8. shell编程学习笔记之标准输入输出(read&echo)

    2017-07-17 09:32:07 输入read: 用途: 从标准输入读取一行,或者从文件描述符FD(file descriptor)中读取一行,并且将其分割成字段. 用法: read [-ers ...

  9. idea通过springboot初始化器新建项目

    1.通过初始化器新建项目,勾选后 对应生成的pom文件 以及生成的包路径 2.生成项目后点击稍后弹出的自动自动导入maven工程的改变,当pom中有依赖改变时会自动刷新导入依赖 3.删除自动生成项目的 ...

  10. quartz(7)-源码分析

    定时器启动 上图通过spring加载quartz <bean id="scheduler" class="org.springframework.schedulin ...