django的模型层(二)
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的模型层(二)的更多相关文章
- {django模型层(二)多表操作}一 创建模型 二 添加表记录 三 基于对象的跨表查询 四 基于双下划线的跨表查询 五 聚合查询、分组查询、F查询和Q查询
Django基础五之django模型层(二)多表操作 本节目录 一 创建模型 二 添加表记录 三 基于对象的跨表查询 四 基于双下划线的跨表查询 五 聚合查询.分组查询.F查询和Q查询 六 xxx 七 ...
- day 70 Django基础五之django模型层(二)多表操作
Django基础五之django模型层(二)多表操作 本节目录 一 创建模型 二 添加表记录 三 基于对象的跨表查询 四 基于双下划线的跨表查询 五 聚合查询.分组查询.F查询和Q查询 六 ORM ...
- day 56 Django基础五之django模型层(二)多表操作
Django基础五之django模型层(二)多表操作 本节目录 一 创建模型 二 添加表记录 三 基于对象的跨表查询 四 基于双下划线的跨表查询 五 聚合查询.分组查询.F查询和Q查询 六 ORM ...
- 64、django之模型层(model)--建表、查询、删除基础
要说一个项目最重要的部分是什么那铁定数据了,也就是数据库,这篇就开始带大家走进django关于模型层model的使用,model主要就是操纵数据库不使用sql语句的情况下完成数据库的增删改查.本篇仅带 ...
- 67、django之模型层(model)--查询补充及mookie
本篇导航: F查询与Q查询 cookie 一.F查询与Q查询 1.以Book表为例 class Book(models.Model) : title = models.CharField(max_le ...
- django之模型层(model)--建表、查询、删除基础
要说一个项目最重要的部分是什么那铁定数据了,也就是数据库,这篇就开始带大家走进django关于模型层model的使用,model主要就是操纵数据库不使用sql语句的情况下完成数据库的增删改查.本篇仅带 ...
- django之模型层(model)--查询补充及cookie
已经连续写了好几篇django的模型层(model)增删改查的随笔了,没篇大篇幅都是查询相关的操作,可以看出查询在数据的操作中是多么的重要,而本篇最后再补充一点关于关于查询的一些方法,模型层基本的操作 ...
- python 全栈开发,Day70(模板自定义标签和过滤器,模板继承 (extend),Django的模型层-ORM简介)
昨日内容回顾 视图函数: request对象 request.path 请求路径 request.GET GET请求数据 QueryDict {} request.POST POST请求数据 Quer ...
- Django基础(2)--模板自定义标签和过滤器,模板继承 (extend),Django的模型层-ORM简介
没整理完 昨日回顾: 视图函数: request对象 request.path 请求路径 request.GET GET请求数据 QueryDict {} request.POST POST请求数据 ...
- Django之模型层(2)
Django之模型层(2) 一.创建模型 实例:我们来假定下面这些概念,字段和关系. 作者模型:一个作者由姓名和年龄. 作者详细模型:把作者的详情放到详情表,包含生日,手机号,家庭住址等信息.作者详情 ...
随机推荐
- 自从学习了MongoDB高可用,慢慢的喜欢上了它,之前确实冷落了
大家好,我是哪吒,最近项目在使用MongoDB作为图片和文档的存储数据库,为啥不直接存MySQL里,还要搭个MongoDB集群,麻不麻烦? 让我们一起,一探究竟,继续学习MongoDB高可用和片键策略 ...
- 最长上升子序列 II 时间复杂度(nlogn)
题目:最长上升子序列 II 给定一个长度为 N 的数列,求数值严格单调递增的子序列的长度最长是多少. 输入格式 第一行包含整数 N. 第二行包含 N个整数,表示完整序列. 输出格式 输出一个整数,表示 ...
- Emacs单文件配置
编辑 ~/.emacs 输入以下内容 ;; 编码 (set-language-info "UTF-8" 'coding-priority '(utf-8 gb18030 gbk g ...
- evil 控制窗口大小,比快捷键方便
下面是vim原本的支持的键 可以用于 emacs evil ,evil 用这个比用快捷键还方面些 1.纵向调整 :res[ize] num 指定当前窗口为num列num行 :res[ize] +num ...
- FAS2720 配置
FAS 2720配置操作 第1章 初始化 1.1设备物理安装 1.1.1组件介绍 机头FAS 2720 (2U) 前面板 后面 1.1.2准备工作 (1)工具准备 螺丝刀.网线.Console线. ...
- 我Alfred Workflow工具集合
MyToolBox 我常用的工具箱,Alfred Workflow工具集合满足日常开发使用场景.不断完善和更新Alfred Workflow. 目前包含一下功能. 时间戳转换 unicode转中文 随 ...
- 学习ASP.NET Core Blazor编程系列二十七——JWT登录(1)
学习ASP.NET Core Blazor编程系列文章之目录 学习ASP.NET Core Blazor编程系列一--综述 学习ASP.NET Core Blazor编程系列二--第一个Blazor应 ...
- K8S Pod Sidecar 应用场景之一-加入 NGINX Sidecar 做反代和 web 服务器
Kubernetes Pod Sidecar 简介 Sidecar 是一个独立的容器,与 Kubernetes pod 中的应用容器一起运行,是一种辅助性的应用. Sidecar 的常见辅助性功能有这 ...
- key对象转换数组title
before <!DOCTYPE HTML> <html> <head> <title>key对象转换数组title</title> < ...
- Postgresql invalid command \N数据恢复处理
做一个单表恢复工作,数据在1000多W,说是报了错误导不进去,环境与流程见下:恢复步骤: 1.导出语句 pg_dump -h xxxxx -p 5432 -U postgres -b -Fp db_t ...