一. 多表操作

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

  一对多

  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. ThreadLocalSingleton.h——base

    #ifndef MUDUO_BASE_THREADLOCALSINGLETON_H #define MUDUO_BASE_THREADLOCALSINGLETON_H #include <boo ...

  2. DRF (Django REST framework) 中的路由Routers

    路由Routers 注意是:对于视图集ViewSet!!!我们除了可以自己手动指明请求方式与动作action之间的对应关系外,还可以使用Routers来帮助我们快速实现路由信息. REST frame ...

  3. [系列] 使用 go modules 包管理工具(一)

    目录 概述 初始化 添加依赖包 go mod 命令 小结 源码地址 概述 我想实现一个开箱即用的 API 框架的轮子,这个轮子是基于 Gin 基础上开发的. 为什么是开箱即用,它会集成哪些功能? 以上 ...

  4. OSG与Shader的结合使用

    目录 1. 概述 2. 固定管线着色 3. 纹理着色 4. 参考 1. 概述 以往在OpenGL中学习渲染管线的时候,是依次按照申请数据.传送缓冲区.顶点着色器.片元着色器这几个步骤编程的.OSG是O ...

  5. ionic $ioniActionSheet 在安卓手机没样式

    解决方法: 添加以下修复css样式 /** * Action Sheets for Android * ------------------------------------------------ ...

  6. 04_枚举类型iota

    iota是枚举类型的关键字,使用iota可以方便快捷的给常量赋值,主要体现在以下几个方面:1.iota常量自动生成器,每个一行加12.iota给常量赋值使用3.iota遇到const重置为04.可以写 ...

  7. awrcrt更新到2.17 ,添加了top SQL list

    应广大Oracle专家,教授的要求(被问了很多次,什么时候添加top sql 啊~~,最近一年由于很少交付巡检类的服务,所以没有机会更新)>终于为awrcrt更新了Top SQL list,版本 ...

  8. Nginx入门(二):镜像和容器

    0.docker常用命令 #镜像名 版本标签 镜像id 创建时间 镜像大小 REPOSITORY TAG IMAGE ID CREATED SIZE hello-world latest fce289 ...

  9. 如何使用有道云笔记的Markdown----初级版?

    我一般整理笔记用的是用有道云笔记,在这里,Markdown怎么用? 什么是Markdown?Markdown是一种轻量级的「标记语言」,通常为程序员群体所用,目前它已是全球最大的技术分享网站 GitH ...

  10. POJ-3169 Layout (差分约束+SPFA)

    POJ-3169 Layout:http://poj.org/problem?id=3169 参考:https://blog.csdn.net/islittlehappy/article/detail ...