django的模型层(二)

一 创建模型

from django.db import models

# Create your models here.

class Author(models.Model):
nid = models.AutoField(primary_key=True)
name = models.CharField(max_length=32)
age = models.IntegerField() # 一对一
authordetail = models.OneToOneField(to="AuthorDetail", to_field="nid", on_delete=models.CASCADE) def __str__(self):
return self.name # 作者详情表
class AuthorDetail(models.Model):
nid = models.AutoField(primary_key=True)
birthday = models.DateField()
telephone = models.BigIntegerField()
addr = models.CharField(max_length=64) # 出版社表
class Publish(models.Model):
nid = models.AutoField(primary_key=True)
name = models.CharField(max_length=32)
city = models.CharField(max_length=32)
email = models.EmailField() def __str__(self):
return self.name class Book(models.Model):
nid = models.AutoField(primary_key=True)
title = models.CharField(max_length=32)
publishDate = models.DateField()
price = models.DecimalField(max_digits=5, decimal_places=2) # 一对多关系
publish = models.ForeignKey(to="Publish",to_field="nid",on_delete=models.CASCADE) '''
publish_id INT ,
FOREIGN KEY (publish_id) REFERENCES publish(id) ''' # 多对多
authors = models.ManyToManyField(to="Author") '''
CREATE TABLE book_authors(
id INT PRIMARY KEY auto_increment ,
book_id INT ,
author_id INT ,
FOREIGN KEY (book_id) REFERENCES book(id),
FOREIGN KEY (author_id) REFERENCES author(id)
)
''' # class Book2Author(models.Model):
#
# nid = models.AutoField(primary_key=True)
# book=models.ForeignKey(to="Book")
# author=models.ForeignKey(to="Author") def __str__(self):
return self.title

二 添加表记录

1 一对多

    # 方式 1
book_obj = Book.objects.create(title="水浒传",publishDate="2018-01-01",price="100",publish_id=1) print(book_obj.title) # 水浒传 # 方式2
pub_obj = Publish.objects.filter(nid=1).first()
# print(pub_obj)
book_obj = Book.objects.create(title="三国演义1", price=100, publishDate="2012-12-12", publish=pub_obj)
print(book_obj.title)
print(book_obj.price)
print(book_obj.publishDate)
print(book_obj.publish) #与这本书籍关联的出版社对象 print(book_obj.publish.name)
print(book_obj.publish.email)
print(book_obj.publish_id) # 查询水浒传的出版社对应的邮箱
book_obj = Book.objects.filter(title="水浒传").first()
print(book_obj.publish.email)

2 多对多

    book_obj=Book.objects.create(title="gogo",price=100,publishDate="2012-12-12",publish_id=1)

    egon=Author.objects.get(name="egon")
alex=Author.objects.get(name="alex") # #绑定多对多关系的API
book_obj.authors.add(egon,alex)
#
book_obj.authors.add(1,2,3)
book_obj.authors.add(*[1,2,3])
#
#
#
# #解除多对多关系
#
book=Book.objects.filter(nid=4).first()
book.authors.remove(2)
#book.authors.remove(*[1,2]) book.authors.clear()

三  基于对象的跨表查询

基于对象的跨表查询(子查询)

1 一对多

# 一对多查询的正向查询: 查询水浒传这本书的出版社名字
book_obj = Book.objects.filter(title="水浒传").first()
print(book_obj.publish.name) # 对应sql:
#select publish_id from Book where title="水浒传"
#select name from Publish where id=1 # 一对多 反向查询 查询人民出版社出版过的书籍名称
pub_obj = Publish.objects.filter(name="人民出版社").first()
book_list = pub_obj.book_set.all()
print(book_list)
正向查询   A--------->B
反向查询 B<---------A ===============================
一对多查询
正向查询: 按字段
反向查询: 表名小写_set.all() book_obj.publish
Book(关联属性:publish) ---------------------> Publish
<---------------------
publish_obj.book_set.all()
 

2 多对多

#多对多正向查询: 查询水浒传这本书作者名字
book_obj = Book.objects.filter(title="水浒传").last()
author_list = book_obj.authors.all() for author in author_list:
print(author.name) # 多对多反向查询 查询alex出版过的书籍 alex_obj = Author.objects.filter(name="alex").last()
book_list = alex_obj.book_set.all()
# print(book_list) for book in book_list:
print(book.title)
正向查询   A--------->B
反向查询 B<---------A =============================== 多对多查询:
正向查询: 按字段
反向查询: 表名小写_set.all() book_obj.anthors.all()
Book(关联属性:publish)对象 ---------------------> Author
<---------------------
author_obj.book_set.all() #quertset

3 一对一

 # 一对一查询的正向查询 : 查询alex的手机号

alex=Author.objects.filter(name="alex").first()
print(alex.authordetail.telephone) # 一对一查询的反向查询 : 查询手机号为110的作者的名字和年龄
ad=AuthorDetail.objects.filter(telephone="123").first()
print(ad.author.name)
# print(ad.author.age)
一对一查询:
正向查询: 按字段
反向查询: 表名小写 author.authordetail
Author(关联属性:publish)对象 ---------------------> AuthorDetail
<---------------------
authordetail_obj.author

四 基于双下划线的跨表查询

SQL join

1 一对多

正向查询: 按字段
反向查询: 表名小写
    '''
正向查询按字段,反向查询按表名小写用来告诉ORM引擎join哪张表
''' '''
sql 语句 SELECT app01_publish.name from app01_book INNER JOIN app01_publish
on app01_book.publish_id = app01_publish.nid
where app01_book.title="水浒传"; '''
查询水浒传这本书的出版社的名字
# 方式一
book_obj = Book.objects.filter(title="水浒传").values("publish__name")
print(book_obj)
# <QuerySet [{'publish__name': '人民出版社'}]> # 方式二
ret = Publish.objects.filter(book__title="水浒传").values("name")
print(ret)
# <QuerySet [{'name': '人民出版社'}]>

2 多对多

SELECT app01_author.name from app01_book INNER JOIN  app01_book_authors
on app01_book.nid = app01_book_authors.book_id
INNER JOIN app01_author
on app01_book_authors.author_id = app01_author.nid
where app01_book.title="三国演义";
查询三国演义这本书的所有作者的名字
# 方式一
# 需求: 通过Book表join与其关联的Author表,属于正向查询:按字段authors通知ORM引擎join book_authors与author
ret = Book.objects.filter(title="三国演义").values("authors__name")
print(ret) # 方式二
# 需求: 通过Author表join与其关联的Book表,属于反向查询:按表名小写book通知ORM引擎join book_authors与book表
ret = Author.objects.filter(book__title="三国演义").values("name") print(ret)
# < QuerySet[{'name': 'alex'}, {'name': 'egon'}] >

3 一对一

查询alex的手机号

# 方式一
# 需求: 通过Author表join与其关联的AuthorDetail表,属于正向查询:按字段authordetail通知ORM引擎join Authordetail表
ret = Author.objects.filter(name="alex").values("authordetail__telephone")
print(ret )
# <QuerySet [{'authordetail__telephone': 123}]> # 方式二
# 需求: 通过AuthorDetail表join与其关联的Author表,属于反向查询:按表名小写author通知ORM引擎join Author表
ret = AuthorDetail.objects.filter(author__name="alex").values("telephone")
print(ret)
# <QuerySet [{'telephone': 123}]>

4 进阶练习

手机号以112开头的作者出版过的所有书籍名称以及书籍出版社名称
SELECT
app01_book.title,
app01_publish. NAME
FROM app01_book
INNER JOIN app01_book_authors ON app01_book.nid = app01_book_authors.book_id
INNER JOIN app01_author ON app01_book_authors.author_id = app01_author.nid
INNER JOIN app01_authordetail ON app01_author.authordetail_id = app01_authordetail.nid
INNER JOIN app01_publish ON app01_book.publish_id = app01_publish.nid
WHERE app01_authordetail.telephone = 112;
# 方式一
# 需求: 通过Book表join AuthorDetail表, Book与AuthorDetail无关联,所以必需连续跨表
ret =Book.objects.filter(authors__authordetail__telephone="112").values("title","publish__name")
print(ret) # 方式二
ret = Author.objects.filter(authordetail__telephone="112").values("book__title","book__publish__name")
print(ret)

五 聚合与分组查询

聚合 aggregate:返回值是一个字典,不再是queryset

1. 聚合查询

查询所有书籍的平均价格

from django.db.models import  Avg,Max,Min,Count
# select count(price) from app01__book
ret = Book.objects.all()..aggregate(price_agv = Avg("price"))
print(ret)

2. 分组查询-- 单表查询

① 查询每一个部门的名称以及员工的平均薪水
from django.db.models import Avg, Max, Min, Count

ret = Emp.objects.values("dep").annotate(salary_avg = Avg("salary")).values("dep","salary_avg")
print(ret)
# <QuerySet [{'dep': '销售部', 'salary_avg': 10000.0}, {'dep': '人事部', 'salary_avg': 3333.0}]> # 单表分组查询的ORM语法: 单表模型.objects.values("group by 的字段").annotate(聚合函数的统计字段)
② 查询每一个省份的名称以及员工数
ret = Emp.objects.values("province").annotate(c = Count("id")).values("province","c")
print(ret )

# <QuerySet [{'province': '山东', 'c': 1}, {'province': '河北', 'c': 1}]>

 ③ 补充知识点

ret = Emp.objects.all()
print(ret) # select * from emp ret = Emp.objects.values("name")
print(ret) # select name from emp; # Emp.objects.all().annotate(avg_salary=Avg("salary"))
# SELECT avg(salary) from app01_emp GROUP BY id
# 没有意义 单表

2. 分组查询-- 多表查询

① 查询每一个出版社的名称以及出版的书籍个数
SELECT
app01_publish. NAME,
count(app01_book.title)
FROM
app01_book
INNER JOIN app01_publish ON app01_book.publish_id = app01_publish.nid
from django.db.models import Avg, Max, Min, Count

# ret = Publish.objects.values("nid").annotate(c=Count("book__title"))
ret = Publish.objects.values("nid").annotate(c=Count("book__title")).values("name", "c")
print(ret)
② 查询每一个作者的名字以及出版过的书籍的最高价格
SELECT
app01_author. NAME,
MAX(app01_book.price)
FROM
app01_author
INNER JOIN app01_authordetail ON app01_author.nid = app01_authordetail.nid
INNER JOIN app01_book_authors ON app01_author.nid = app01_book_authors.author_id
INNER JOIN app01_book ON app01_book_authors.book_id = app01_book.nid
GROUP BY
app01_author.nid
ret = Author.objects.values("pk").annotate(max_price=Max("book__price")).values("name","max_price")
print(ret)
# <QuerySet [{'name': 'alex', 'max_price': Decimal('300.00')}, {'name': 'egon', 'max_price': Decimal('300.00')}]>
③ 查询每一个书籍的名称以及对应的作者个数
SELECT DISTINCT
`app01_book`.`title`,
COUNT(`app01_author`.`name`) AS `c`
FROM
`app01_book`
INNER JOIN `app01_book_authors` ON (
`app01_book`.`nid` = `app01_book_authors`.`book_id`
)
INNER JOIN `app01_author` ON (
`app01_book_authors`.`author_id` = `app01_author`.`nid`
)
GROUP BY
`app01_book`.`nid`
ret = Book.objects.values("pk").values(c=Count("authors__name")).values("title","c").distinct()
print(ret)
# <QuerySet [{'title': '水浒传', 'c': 2}, {'title': '三国演义', 'c': 2}]>

django的模型层(二)的更多相关文章

  1. {django模型层(二)多表操作}一 创建模型 二 添加表记录 三 基于对象的跨表查询 四 基于双下划线的跨表查询 五 聚合查询、分组查询、F查询和Q查询

    Django基础五之django模型层(二)多表操作 本节目录 一 创建模型 二 添加表记录 三 基于对象的跨表查询 四 基于双下划线的跨表查询 五 聚合查询.分组查询.F查询和Q查询 六 xxx 七 ...

  2. day 70 Django基础五之django模型层(二)多表操作

    Django基础五之django模型层(二)多表操作   本节目录 一 创建模型 二 添加表记录 三 基于对象的跨表查询 四 基于双下划线的跨表查询 五 聚合查询.分组查询.F查询和Q查询 六 ORM ...

  3. day 56 Django基础五之django模型层(二)多表操作

    Django基础五之django模型层(二)多表操作   本节目录 一 创建模型 二 添加表记录 三 基于对象的跨表查询 四 基于双下划线的跨表查询 五 聚合查询.分组查询.F查询和Q查询 六 ORM ...

  4. 64、django之模型层(model)--建表、查询、删除基础

    要说一个项目最重要的部分是什么那铁定数据了,也就是数据库,这篇就开始带大家走进django关于模型层model的使用,model主要就是操纵数据库不使用sql语句的情况下完成数据库的增删改查.本篇仅带 ...

  5. 67、django之模型层(model)--查询补充及mookie

    本篇导航: F查询与Q查询 cookie 一.F查询与Q查询 1.以Book表为例 class Book(models.Model) : title = models.CharField(max_le ...

  6. django之模型层(model)--建表、查询、删除基础

    要说一个项目最重要的部分是什么那铁定数据了,也就是数据库,这篇就开始带大家走进django关于模型层model的使用,model主要就是操纵数据库不使用sql语句的情况下完成数据库的增删改查.本篇仅带 ...

  7. django之模型层(model)--查询补充及cookie

    已经连续写了好几篇django的模型层(model)增删改查的随笔了,没篇大篇幅都是查询相关的操作,可以看出查询在数据的操作中是多么的重要,而本篇最后再补充一点关于关于查询的一些方法,模型层基本的操作 ...

  8. python 全栈开发,Day70(模板自定义标签和过滤器,模板继承 (extend),Django的模型层-ORM简介)

    昨日内容回顾 视图函数: request对象 request.path 请求路径 request.GET GET请求数据 QueryDict {} request.POST POST请求数据 Quer ...

  9. Django基础(2)--模板自定义标签和过滤器,模板继承 (extend),Django的模型层-ORM简介

    没整理完 昨日回顾: 视图函数: request对象 request.path 请求路径 request.GET GET请求数据 QueryDict {} request.POST POST请求数据 ...

  10. Django之模型层(2)

    Django之模型层(2) 一.创建模型 实例:我们来假定下面这些概念,字段和关系. 作者模型:一个作者由姓名和年龄. 作者详细模型:把作者的详情放到详情表,包含生日,手机号,家庭住址等信息.作者详情 ...

随机推荐

  1. CF1779C Least Prefix Sum 题解

    CF链接:Least Prefix Sum Luogu链接:Least Prefix Sum $ {\scr \color {CornflowerBlue}{\text{Solution}}} $ 先 ...

  2. DVWA靶场实战(十一)——XSS(Reflected)

    DVWA靶场实战(十一) 十一.XSS(Reflected): 1.漏洞原理: XSS被称为跨站脚本攻击(Cross Site Script),而Reflected被称作反射型XSS.不同于DOM和S ...

  3. VMware vSphere vCenter ServerAppliance 7.0安装配置

    VMware vSphere vCenter ServerAppliance 7.0安装配置 环境说明: 1.将vCenter ServerAppliance部署在ESXi主机上,安装配置好ESXi主 ...

  4. Sublime下运行javascript,并带彩色提示

    最近和各种同事磨合技术,自闭中~ 首先让JS在Sublime上运行 去下载Node.js并且安装 安装完成后 cmd 输入 node -v 查看安装是否成功. 接着打开Sublime - 工具 > ...

  5. 【Python】bytes和hex字符串之间的相互转换

    十六进制字符串:a="CC DD 01 61 F6 01 00 64 A4 81 00 00 00 8B" b=bytes.fromhex(a) 转为字节 from socket ...

  6. 线程基础知识02-CompletableFuture

    1 简介 Futrue可以监视目标线程调用call的情况,当你调用Future的get()方法以获得结果时,调用方的线程就被阻塞,直到目标线程的call方法结束并返回结果. 线程的实现方式有几种方式, ...

  7. SpringMVC返回值类型及响应数据类型

    1.SpringMVC 和 Struts2 的优略分析 共同点: 它们都是表现层框架,都是基于 MVC 模型编写的. 它们的底层都离不开原始 ServletAPI. 它们处理请求的机制都是一个核心控制 ...

  8. git操作出现 error: The following untracked working tree files would be overwritten by ...

    命令行:git clean -d -fx,作用是:删除没有git add 的文件 ,执行之后解决了 error: The following untracked working tree files ...

  9. uniapp 分享 绘制海报

    小程序分享海报,由于微信的限制,暂时无法直接分享小程序到朋友圈(虽然微信开发者工具基础库从2.11.3开始支持分享小程序到朋友圈,但目前仍处于Beta中)所以生成海报仍然还是主流方式 主体思路:将设计 ...

  10. 交叉熵损失CrossEntropyLoss

    在各种深度学习框架中,我们最常用的损失函数就是交叉熵,熵是用来描述一个系统的混乱程度,通过交叉熵我们就能够确定预测数据与真实数据的相近程度.交叉熵越小,表示数据越接近真实样本. 1 分类任务的损失计算 ...