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. 基于Docker安装的Stable Diffusion使用CPU进行AI绘画

    基于Docker安装的Stable Diffusion使用CPU进行AI绘画 由于博主的电脑是为了敲代码考虑买的,所以专门买的高U低显,i9配核显,用Stable Diffusion进行AI绘画的话倒 ...

  2. 使用字节流丢读取中文的问题-Reader类

    使用字节流丢读取中文的问题 当使用字节流读取文本文件时,可能会有一个小问题.就是遇到中文字符时,可能不会显示完整的字符,那是因为一个中文字符可能占用多个字节存储.所以Java提供一些字符流类,以字符为 ...

  3. python学习day 02

    昨日内容回顾 typora软件 1.作为一款逐年火爆的文本编辑器,深受IT行业的喜爱. 2.下载与安装: windows用群里发的软件 macOS下载地址:https://mac.qdrayst.co ...

  4. 视觉十四讲:第十二讲_RGB-D稠密点云

    1.点云地图 所谓点云,就是由一组离散的点表示的地图,最基本的点包含x,y,z三维坐标,也可以带有r,g,b的彩色信息. #include <iostream> #include < ...

  5. XML02

    组成部分: 1. 文档声明 1. 格式: 2. 属性列表: * version:版本号,必须的属性 * encoding:编码方式.告知解析引擎当前文档使用的字符集,默认值:ISO-8859-1 * ...

  6. Spring IOC官方文档学习笔记(十一)之使用JSR 330标准注解

    1.使用@Inject和@Named进行依赖注入 (1) Spring提供了对JSR 330标准注解的支持,因此我们也可以使用JSR 330标准注解来进行依赖注入,不过,在此之前,我们得先使用mave ...

  7. Nacos服务发现原理分析

    微服务将自己的实例注册到nacos注册中心,nacos服务端存储了注册列表,然后通过ribbon调用服务,具体是如何调用?如果nacos服务挂了,还能正常调用服务吗?调用的服务列表发生变化,调用方是如 ...

  8. Redis 源码解读之 Rehash 的调用时机

    Redis 源码解读之 Rehash 的调用时机 背景和问题 本文想要解决的问题 什么时机触发 Rehash 操作? 什么时机实际执行 Rehash 函数? 结论 什么时机触发 Rehash 操作? ...

  9. JumpServer(v2.28.6) 堡垒机常见问题

    JumpServer 各组件查询日志方法 # 默认持久化目录 /data/jumpserver ls -al /data/jumpserver/core/logs ls -al /data/jumps ...

  10. socket.io实现简易聊天室功能

    本文简单介绍使用websocket实现一个简单的聊天室功能,我这里是用vite初始化的vue3项目. 在线体验地址:http://chat.lb0125.com/chat 需要安装的库: socket ...