一. 多表操作

  数据库表关系之关联字段与外键约束

  一对多

  book(多)

  publish(一)

  查询<<水浒传>>这本书出版社的地址:

select publish_id from Book where title="水浒传"
select addr from Publish where id=1

  一旦确定了一对多的关系: 建立一对多的关系,在多的一方建立关联字段(publish_id)

  多对多:

  book

  author

  book2author:

  panshao出版过得书籍名称(子查询)

select id from author where name='panshao';    # 在作者表中拿出panshao
select book_id from book2author where author_id=1; # 找出作者id等于1的书籍的id
select title from book where id=book_id;

  一旦确定表关系是多对对: 创建第三张表  id   book_id     author_id

  一对一:

  author

  authordetail

  一旦确定是一对多的关系: 建立一对多的关系=======>在多的表中建立关联字段   (一个出版社可以出版多本书)

  一旦确定为多对多的关系: 建立多对多的关系========> 创建第三张表(关联表): id和两个关联字段(一本书可以有多个作者,一个作者可以出版多本书)

  一旦确定一对一关系: 建立一对一的关系========>在两张表中任意一张表中建立关联字段+unique(一个作者只有一个详细信息)

  数据库表关系之创建关联表

from django.db import models

class Book(models.Model):
title = models.CharField(max_length=32)
price = models.DecimalField(max_digits=8, decimal_places=2)
publish_time = models.DateField(auto_now_add=True)
# 外键关系
publish = models.ForeignKey(to='Publish') # 默认关联的是主键,如果相关联其他字段则可以使用to_field=
authors = models.ManyToManyField(to='Author') # 告诉数据库让建一个多对多的表,在这里只是标识 class Publish(models.Model):
name = models.CharField(max_length=32)
addr = models.CharField(max_length=32)
# email = models.EmailField() class Author(models.Model):
name = models.CharField(max_length=32)
age = models.IntegerField()
authordetail = models.OneToOneField(to='AuthorDetail') class AuthorDetail(models.Model):
phone = models.CharField(max_length=32)
addr = models.CharField(max_length=32)

  注意事项:

  1. id字段是自动添加的

  2. 对于外键字段, Django会在字段上自动添加"_id"来创建数据库中的列名

  3. 外键字段foreignkey有一个null=True 的设置(他允许外检接受空值NULL), 你可以赋给他空值None

  一对一就是OnetoOneField;一对多就是ForeignKey;他俩是一样的,会在那张表中生成一个字段,加一个_id+一个约束关系;多对多就是ManyToManyField,生成一个第三张关系表

2. 多表操作

  一对多增删改查

# book_obj = models.Book.objects.create(title='都是东游记',price=108, publish_id=1 )
print(book_obj.title) # 返回值book_obj就是添加记录的对象 方式二:
publish_obj= models.Publish.objects.filter(id=2).first() # 查询id为2的出版社对象;不加first就是queryset的那个集合
book_obj = models.Book.objects.create(title='西游记', price=345.45, publish=publish_obj) # publish就是Book表里面的那个字段 # 让他等于publish的一个实例模型对象,赋值给publish_obj给了他一个对象,相当于把方式一的方法给翻译过来了

  改:

book_obj = models.Book.objects.filter(pk=1).update(publish_id=3)  # 拿出book_id等于1 的书籍把他的出版社id改为其他的出版社
方式二: 传对象
publish_obj = models.Publish.objects.filter(pk=4).first() # 拿出id等于4 的出版社
models.Book.object.filter(pk=1).update(publish=publish_obj) # 将id等于1 的书籍的出版社改为id等于4 的出版社id

  删除:

models.Book.objects.filter(pk=1).delete()  # 将id为1的书籍进行删除
models.Publish.objects.filter(pk=1).delete() # 将publish_id为1的书籍进行删除

  多对多的增删改查

# 该主键为1的书籍添加两个作者
# 思路: 先拿出主键唯一的书籍
book_obj = models.Book.objects.filter(pk=15).first()
print(book_obj.authors) # 对象点击多对多虚拟字段,会直接跨到多对多的第三张表 book_obj.authors.add(2,3) # 将id等于1,3 的作者添加至第三张表中 方式二:
author_obj = models.Author.objects.filter(pk=15).first()
book_obj.authors.add(author_obj)

  add给书籍添加作者,括号内既可以传数字也可以传对象,并且可以支持一次性传多个,用逗号隔开就行

  改:

book_obj = models.Book.objects.filter(pk=15).first()   # 拿出id等于15的书籍
book_obj.authors.set([2,3]) # 将id等于15的书籍作者设置为2, 3 # 将主键为15的书籍改为作者为2, 3
book_obj = models.Book.objects.filter(pk=15).first()
# book_obj.authors.set([2,3])
author_obj = models.Author.objects.filter(pk=3).first()
book_obj.authors.set([author_obj,]) # 自动将author_obj的id值直接传进来

  set()括号内,需要传一个可迭代对象,可迭代对象中可以是多个数字的组合,也可以是多个对象组合,但是不要混着用!!!

  删除:

book_obj = models.Book.objects.filter(pk=15).first()
book_obj.authors.remove(2) # 删除作者为2的那条数据 author_obj = models.Author.objects.filter(pk=1).first()
# author_obj1 = models.Author.objects.filter(pk=2).first()
# author_obj2 = models.Author.objects.filter(pk=3).first()
# book_obj.authors.remove(author_obj) # id等于1的作者删除
# book_obj.authors.remove(author_obj1,author_obj2)

  remove()括号内既可以传数字,也可以传对象,并且支持传多个,逗号隔开

将某本书跟作者的关系全部清空
book_obj = models.Book.objects.filter(pk=1).first()
book_obj.authors.clear() # 清空当前书籍与作者的所有关系

3. 跨表查询

  正向与反向的概念

  正向: 外键字段在当前查询的对象里面,由这个对象查另外一张表,就是正向查询

  反向: 关系字段不在当前对象中,当前字段没有标识

# 一对一
# 正向:author---关联字段在author表里--->authordetail 按字段
# 反向:authordetail---关联字段在author表里--->author 按表名小写 # 一对多
# 正向:book---关联字段在book表里--->publish 按字段
# 反向:publish---关联字段在book表里--->book 按表名小写_set.all() 因为一个出版社对应着多个图书 # 多对多
# 正向:book---关联字段在book表里--->author 按字段
# 反向:author---关联字段在book表里--->book 按表名小写_set.all() 因为一个作者对应着多个图书 正向查询按外键字段
反向查询按表名小写
"""
"""基于对象的跨表查询(子查询:将一张表的查询结果当做另外一个查询语句的条件)"
  

  基于对象的跨表查询(子查询:将一张表的查询结果当做另外一张表查询语句的条件)

1. 查询书籍id是15的出版社的名称
book_obj = models.Book.objects.filter(pk=15).first() # 先拿出id为15的书籍
print(book_obj.publish.name) # 外键关系在book内,正向查询,直接 . publish就行 2. 查询书籍id为15 的作者的姓名
book_obj = models.Book.objects.filter(pk=15).first()
print(book_obj.authors.all())
res = book_obj.authors.all()
for i in res:
print(i.name) # 当我们在遇到app01.Author.None时,不要慌张,有可能是在authors后面缺少一个all()
3.查询作者是panshao的家庭住址
author_obj = models.Author.objects.filter(name='panshao').first() # 拿出叫panshao的这个人名字
print(author_obj.authordetail.addr) # 进行正向查询 4.查询出版社是攀少网络传媒出版社出版的书籍
publish_obj = models.Publish.objects.filter(name='攀少网络传媒出版').first()
print(publish_obj.book_set.all())
5. 查询作者是panshao的写过的所有的书籍
publish_obj = models.Author.objects.filter(name='panshao').first()
print(publish_obj.book_set.all()) 6. 查询电话是130的作者名字
author_detail_obj = models.AuthorDetail,obj.filter(phone=130).first()
print(author_detail_obj.author.name) # 当我们反向查询的结果是多个的时候就需要我们去加_set,,,,,,,,当你反向查询的结果是多个的时候 就需要加_set,,否则直接表明小写即可

  

查询书籍id为15的作者的电话号码
book_obj = models.Book.object.filter(pk=15).first()
author_list = book_obj.authors.all()
for author_obj in author_list:
print(author_obj.author_detail.phone)

  基于双下划线的跨表查询(连表查询)

1. 查询panshao作者的手机号
res = models.Author.objects.filter(name='panhao').values('author_detail__phone') # values是查询某张表的某个字段
print(res) 2. 查询手机号为130的作者姓名
author_detail_obj = models.AuthorDetail.objects.filter(phone=130).values('author__name') 3. 查询panshao这个作者的年龄和手机号:
# 正向
res = models.Author.objects.filter(name='jason').values('age','author_detail__phone')
print(res)
反向
res1 = models.AuthorDetail.objects.filter(author__name='jason').values('phone','author__age')
print(res1) 4. 查询书籍id是1的作者的电话号码
res = models.Book.objects.filter(id=1).values('authors__authordetail__phone')
res1 = models.Book.objects.filter(pk=1).values('外键字段1__外键字段2__外键字段3__普通字段') """只要表里面有外键字段 你就可以无限制跨多张表""

四. 聚合查询

1.统计所有书的总价格(aggregate)
from django.db.models import Max,Min,Count,Avg,Sum
res = models.Book.objects.aggregate(Sum('price'))
res1 = models.Book.objects.aggregate(Avg('price'))
res2 = models.Book.objects.aggregate(Count('price'))
res3 = models.Book.objects.aggregate(Max('price'))
res4 = models.Book.objects.aggregate(Min('price'))
res5 = models.Book.objects.aggregate(Max('price'),Min('price'),Count('pk'),Avg('price'),Sum('price'))
print(res5)
print(res)
print(res1)
print(res2) 分组查询(关键字annotate)
统计每一本书的作者个数
from django.db.models import Max, Min, Count, Avg, Sum
res = models.Book.objects.annotate(author_num = Count('authors')).values('author_num','title') # 按book分组,models后面跟什么就按什么分组
print(res) 统计出每个出版社卖的最便宜的书的价格
res = models.Publish.objects.annotate(mmp = Min('book__price')).values('name','mmp')
print(res) 统计不止一个作者的图书
res = models.Book.objects.annotate(author_num=Count('authors')).filter(author_num__gt=1)
print(res) """
只要是queryset对象 就可以无限制的调用queryset对象的方法!!!
最最常用的就是对一个已经filter过滤完的数据 再进行更细化的筛选 """ # 查询各个作者出的书的总价格
# res = models.Author.objects.annotate(sp=Sum('book__price')).values('name','sp')
# print(res)

五. F查询:

#F查询的本质就是从数据库中获取某个字段的值
# 查询库存数大于卖出数的书籍
"""之前查询等号后面的条件都是我们认为输入的
现在变成了需要从数据库中获取数据放在等号后面
"""
from django.db.models import F
# res = models.Book.objects.filter(kucun__gt=F('maichu'))
# print(res)
# 将书籍库存数全部增加1000
# models.Book.objects.update(kucun=F('kucun')+1000) # 把所有书名后面加上'新款' # from django.db.models.functions import Concat
# from django.db.models import Value
#
# ret3 = models.Book.objects.update(title=Concat(F('title'), Value('新款')))
# models.Book.objects.update(title = F('title')+'新款') # 不能这么写

  

六. q查询

 # Q查询
from django.db.models import Q
# 查询书籍名称是三国演义或者价格是444.44
# res = models.Book.objects.filter(title='三国演义',price=444.44) # filter只支持and关系
# res1 = models.Book.objects.filter(Q(title='三国演义'),Q(price=444)) # 如果用逗号 那么还是and关系
# res2 = models.Book.objects.filter(Q(title='三国演义')|Q(price=444)) # 或关系
# res3 = models.Book.objects.filter(~Q(title='三国演义')|Q(price=444)) # 不是三国演义的书籍
# print(res2) # Q高级用法
q = Q()
q.connector = 'or' # 修改查询条件的关系 默认是and
q.children.append(('title__contains','三国演义')) # 往列表中添加筛选条件
q.children.append(('price__gt',444)) # 往列表中添加筛选条件
res = models.Book.objects.filter(q) # filter支持你直接传q对象 但是默认还是and关系
print(res)

  

django模型层之多表关系的更多相关文章

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

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

  2. Django模型层之单表操作

    Django模型层之单表操作 一 .ORM简介 我们在使用Django框架开发web应用的过程中,不可避免地会涉及到数据的管理操作(如增.删.改.查),而一旦谈到数据的管理操作,就需要用到数据库管理软 ...

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

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

  4. day 69 Django基础五之django模型层(一)单表操作

    Django基础五之django模型层(一)单表操作   本节目录 一 ORM简介 二 单表操作 三 章节作业 四 xxx 一 ORM简介 MVC或者MVC框架中包括一个重要的部分,就是ORM,它实现 ...

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

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

  6. day 55 Django基础五之django模型层(一)单表操作

      Django基础五之django模型层(一)单表操作   本节目录 一 ORM简介 二 单表操作 三 章节作业 四 xxx 一 ORM简介 MVC或者MVC框架中包括一个重要的部分,就是ORM,它 ...

  7. Django模型层(各种表及表数据的操作)

    目录 一.Django模型层 0. django模型层的级联关系 1. 配置django测试脚本 (1)方式一 (2)方式二 2. orm表数据的两种增删改 (1)方式一: (2)方式二: 3. pk ...

  8. web框架开发-Django模型层(2)-多表操作

    很重要,都是精华 多表关系模型 一对一 一旦确定表关系是一对一,在两张表中的任意一张表中建立关联字段+Unique 一对多 一旦确定表关系是一对多,创建关联字段在多的表中 多对多 一旦确定表关系是多对 ...

  9. Django基础五之django模型层(一)单表操作

    一 ORM简介 MVC或者MVC框架中包括一个重要的部分,就是ORM,它实现了数据模型与数据库的解耦,即数据模型的设计不需要依赖于特定的数据库,通过简单的配置就可以轻松更换数据库,这极大的减轻了开发人 ...

随机推荐

  1. 拼写单词[哈希表]----leetcode周赛150_1001

    题目描述: 给你一份『词汇表』(字符串数组) words 和一张『字母表』(字符串) chars. 假如你可以用 chars 中的『字母』(字符)拼写出 words 中的某个『单词』(字符串),那么我 ...

  2. 解决HTML5实现一键拨号、一键发短信及上传头像兼容性问题

    HTML5实现一键拨号,一键发短信以及上传头像等问题都是比较常见的场景,近期在做移动端项目的时候遇到阻挠,通过查找资料解决了问题: 废话不多说,直接上案例代码: HTML5实现一键拨号: <a ...

  3. 自己搭建传统ocr识别项目学习

    大批生成文集训练集: https://www.cnblogs.com/skyfsm/p/8436820.html 基于深度学习的文字识别(3755个汉字) http://www.cnblogs.com ...

  4. Java虚拟机详解(八)------虚拟机监控和分析工具(2)——可视化

    上篇博客我们介绍了虚拟机监控和分析命令行工具,由于其不够直观,不是很容易排查问题,那么本篇博客我们就来介绍几个可视化工具. 1.JConsole JConsole(Java Monitoring an ...

  5. Leetcode之深度优先搜索(DFS)专题-473. 火柴拼正方形(Matchsticks to Square)

    Leetcode之深度优先搜索(DFS)专题-473. 火柴拼正方形(Matchsticks to Square) 深度优先搜索的解题详细介绍,点击 还记得童话<卖火柴的小女孩>吗?现在, ...

  6. Redis设计原理

    1.简介 Redis中的每个Key-Value在内存中都会被划分成DictEntry.RedisObject以及具体对象,其中DictEntry又分别包含指向Key和Value的指针(以RedisOb ...

  7. LeetCode 笔记

    Valid Sudoku 数独整体能够满足的情况是比较复杂.参考:编程之美 关于数独问题的讨论 这道题的解法可能简单一点,因为对输入进行来限制.只是去判断是否是一个数独数独的形式相比较来说也是较简单的 ...

  8. Spring源码解析之ConfigurableApplicationContext

    UML图 接口的作用 从上面的UML图中,可以看到 ConfigurableApplicationContext 直接继承了 ApplicationContext, Lifecycle, Closea ...

  9. 关于hashCode方法的作用

    想要明白hashCode的作用,你必须要先知道Java中的集合. 总的来说,Java中的集合(Collection)有两类,一类是List,再有一类是Set. 你知道它们的区别吗?前者集合内的元素是有 ...

  10. JMeter更改语言为英文

    1. 进入目录apache-jmeter-2.13\bin 2. 打开jmeter.properties 3. 取消“language=en”前的注释 4. 重新打开JMeter,即可看到语言已经变成 ...