一.创建模型

实例:

作者表:
拥有字段:姓名(name),性别(sex),该表与书籍表之间为多对多的关系
作者详情表:
拥有字段:地址(addr),手机号(phone),该表与作者表之间为一对一的关系
出版社表:
拥有字段:名字(name),地址(addr),该表与书籍表之间为一对多的关系
书籍表:
拥有字段:书名(name),单价(price)
分析:一本书可以拥有多个作者,一个作者可以写多本书,所有作者与书籍之间为多对多的关联关系(Many-To-Many);一本书只有一个出版社,但是一个出版社可以出版多种书籍,所以出版社和书籍之间是一对多的关联关系(One-To-Many);作者与作者详情就是一对一关联关系(One-To-One)

所以在Models.py下创建模型如下

class Publish(models.Model):
name = models.CharField(max_length=255)
addr = models.CharField(max_length=255) def __str__(self):
return self.name class Author(models.Model):
id = models.AutoField(primary_key=True)
name = models.CharField(max_length=255)
sex = models.IntegerField()
authordetail = models.OneToOneField(to='AuthorDetail') def __str__(self):
return self.name class AuthorDetail(models.Model):
id = models.AutoField(primary_key=True)
addr = models.CharField(max_length=255)
phone = models.CharField(max_length=255) class Book(models.Model):
id = models.AutoField(primary_key=True)
name = models.CharField(max_length=255)
price = models.DecimalField(max_digits=5, decimal_places=2)
# 外键,关联关系写在一对多中多的那一方
publish = models.ForeignKey(to=Publish)
authors = models.ManyToManyField(to=Author) def __str__(self):
return self.name

注意事项:

1.id字段不写的话会自动添加
2.对于外键字段,Django会在字段名上添加"_id"来创建数据库中的列名
3.外键字段ForeignKey有一个null=True的设置,你可以赋给它空值None

二.添加表记录

一对一:

# 方式一:
detail_obj = models.AuthorDetail.objects.filter(id=2).first()
models.Author.objects.create(name='Yven',sex=1,authordetail=detail_obj) # 方式二:
models.Author.objects.create(name='hwt',sex=2,authordetail_id=1)

一对多:

# 方式一:
publish_obj = models.Publish.objects.filter(id=2).first()
models.Book.objects.create(name='水浒传',price=24.5,publish=publish_obj) # 方式二:
models.Book.objects.create(name='西游记',price=24.5,publish_id=2)

多对多:

# 获得书籍对象
book = models.Book.objects.create(name='水浒传',price=24.5,publish_id=3)
# 获得作者对象
yven = models.Author.objects.get(name='Yven')
hwt = models.Author.objects.get(name='hwt') # 绑定多对多关系
# add中可以传递对象,可以传递id,也可以传递*列表如:(*[yven,hwt])
book.authors.add(yven,hwt) #多对多关系其他常用API:
# 将某个特定的对象从被关联对象集合中去除,可以传递对象,可以传递id,也可以传递*列表如:(*[yven,hwt])
book.authors.remove()
# 清空被关联对象集合,无需传参
book.authors.clear()
# 先清空再设置,传递的参数必须是可迭代对象,一般为列表,列表内可以是对象,也可以是id
book.authors.set()

三.基于对象的跨表查询

一对一查询

正向查询(按字段:authordetail)

# 查询作者姓名为Yven的手机号
yven = models.Author.objects.get(name='Yven')
phone = yven.authordetail.phone

反向查询(按表名小写:author)

# 查询手机号为12221321的作者名
authordetail = models.Author.objects.filter(phont='12221321').first()
name = authordetail.author.name

一对多查询

正向查询(按字段:publish)

# 查询西游记的出版社名
book = models.Book.objects.filter(name='西游记').first()
name = book.publish.name

反向查询(按表名小写_set.all():book_set.all())

# 查询pk为2的出版社出版书籍的单价
publish = models.Publish.objects.filter(pk='2').first()
booklist = publish.book_set.all() #QuerySet对象
for obj in booklist:
print(obj.price)

多对多查询

正向查询(按字段.all():publish.all())

# 查询水浒传的所有作者
book = models.Book.objects.get(name='水浒传')
author = book.authors.all()
for i in author:
print(i.name)

反向查询(按表名小写_set.all():book_set.all())

# 查询Yven写的多少有书籍的单价
author = models.Author.objects.get(name='Yven')
book = author.book_set.all()
for i in book:
print(i.price)

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

Django还提供了一种直观而搞笑的方式在查询(lookups)种表示关联关系,它能自动确认SQL JOIN联系。要做跨关系查询,就使用两个下划线来连接模型(model)间关联字段的名称,知道最终链接到你想要的model为止。

一对一查询

正向查询(按字段):authordetail

# 查询Yven的地址
models.Author.objects.filter(name='Yven').values('authordetail__addr')

反向查询(按表名):author

# 查询Yven的地址
models.AuthorDetail.objects.filter(author__name='Yven').values('addr')

一对多查询

正向查询(按字段):publish

# 查询西游记的出版社名
models.Book.objects.filter(name='西游记').values('publish__name')

反向查询(按表名):book

# 查询西游记的出版社名
models.Publish.objects.filter(book__name='西游记').values('name')

多对多查询

正向查询(按字段):authors

# 查询水浒传的作者性别
models.Book.objects.filter(name='水浒传').values('authors__sex')

反向查询(按表名):book

# 查询水浒传的作者性别
models.Author.objects.filter(book__name='水浒传').values('sex')

五.聚合查询与分组查询

聚合查询:aggregate(*args,**kwargs)

# 需要导入包
from django.db.models import Avg
# 查询所有图书的平均价格
models.Book.objects.all().aggregate(Avg('price'))

aggregate()是QuerySet的一个终止子句,意思是说,它返回一个包含一些键值对的字典。键的名称是聚合值的标识符,值是计算出来的聚合值,键的名称是按照字段和聚合函数的名称自动生成出来的,如果你想要为聚合值指定一个名称,可以向聚合子句提供一个名字。

models.Book.objects.all().aggregate(aaa=Avg('price'))
#{'aaa':3.14}

如果不止有一个聚合查询,可以在aggregate()括号内继续添加参数.

Django提供了以下聚合函数

1.expression
引用模型字段的一个字符串,或者一个query expression
2.output_field
用来表示返回值的model field,一个可选的参数
3.extra
关键字参数可以给聚合函数生成的SQL提供额外的信息
4.Avg
返回给定表达式的平均值,它必须是数值,除非指定不同的output_field
5.Count
返回与expression相关的对象的个数,有一个可选的参数distinct,如果distinct=True,那么Count将只计算唯一的实例,默认值是False
6.Max
返回给定字段的最大值
7.Min
返回给定字段的最小值
8.Sum
返回给定字段的总和

分组查询:annotate()

annotate()为调用QuerySet种每一个对象都生成一个独立的统计值,相当于数据库种的group by

统计每一本书作者个数

from django.db.models import Count
num=Book.objects.annotate(author_num=Count('authors')).values('name','author_num')

总结

values在annotate()之前,表示group by,之后,表示为取值
filter在annotate()之前,表示过滤,之后,表示having

六.F查询与Q查询

F查询

现在位置的操作种,都是将模型字段与常量进行比较,但是,如果想将模型的一个字段与同一个模型的另一个字段进行比较该怎么办?
所有Django为我们提供了F表达式来完成这类操作
导入包: from django.db.models import F

如:查询comment_num数量大于read_num的书籍

models.Book.objects.filter(comment_num__gt=F('read_num'))

还可以对F()对象进行加减乘除,取模等运算操作.

如:将read_num的数量乘以二

models.Book.objects.all().update(read_num=F('read_num')*2)

Q查询

filter()等方法种的关键字参数查询都是通过逗号来实现'AND'的,如果需要执行复杂的查询,就需要使用Q对象
导入包:from django.db.models import Q

可以使用"&"或者"|"或者"~"来组合Q对象,分别表示与,或,非逻辑

如:查询作者为yven或者hwt的书籍信息

models.Book.objects.filter(Q(authors__name='yven') | Q(authors__name='hwt'))

查询函数可以混合使用Q对象和关键字参数,所有提供给查询函数的参数都将"AND"在一起,但是,如果出现Q对象,它必须位于所有关键字参数的前面。

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模型层(一)单表操作

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

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

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

  9. 06.Django基础五之django模型层(二)多表操作

    一 创建模型 表和表之间的关系 一对一.多对一.多对多 ,用book表和publish表自己来想想关系,想想里面的操作,加外键约束和不加外键约束的区别,一对一的外键约束是在一对多的约束上加上唯一约束. ...

  10. Django模型层:单表操作,多表操作,常用(非常用)字段和参数,Django-model进阶

    一.web应用 二.模板的导入与继承 三.静态文件相关 四.inclusion_tag:返回html片段 五.模型层 一.web应用 -s包括两个部分:web服务器+application -目前阶段 ...

随机推荐

  1. P1158 导弹拦截

    P1158 导弹拦截 思路: 按每个点到第一个系统的距离排序,然后预处理出每个点及其之后的点到第二个系统的距离的最大值,再循环一遍枚举答案.  代码: #include <cstdio> ...

  2. js数组的常用操作

    数组合并 var arr=[1,"abc","张三","122"]; var b=["今天天气不错","适合学 ...

  3. 题目1021:统计字符(hash简单应用)

    问题来源 http://ac.jobdu.com/problem.php?pid=1021 问题描述 每次输入两个字符串,统计第一个字符串中的每个字符在第二个字符串中出现的次数. 问题分析 太明显了, ...

  4. Nodejs连接数据库为何使用连接池

    问题一.nodejs既然是单线程运行,在连接数据库时为何要使用连接池呢? 问题二,redis服务端是单线程运行的,使用连接池到redis,服务端还是串行处理,有什么意义么? 这两个问题都涉及到单线程与 ...

  5. BZOJ - 1935 / 1176 cdq分治 三维偏序

    题意:给定n*m的网格,且给出n个(x,y)表示该网格已被占有,q次询问(x1,y1)到(x2,y2)的网格中有多少个被占有,n,m范围1e7,q范围5e5 cdq按x轴排序,树状数组维护y轴 #in ...

  6. mvn修改版本号命令

    mvn -DnewVersion=1.0.0 -DgenerateBackupPoms=false versions:set

  7. iozone文件系统测试工具在AM335x上的移植

     IOzone下载    下载地址:http://www.iozone.org 如下: 解压iozone,并进入到解压路径下的src/current 我的是  iozone3_487 命令:cd  i ...

  8. 关于z-index问题

    关于z-inde,这个网址还是对我受益匪浅的,https://www.cnblogs.com/bigboyLin/p/4621335.html z-index 起作用得有一个前提: 就是和定位一起用, ...

  9. VR内容是如何制作的!

    VR全景视频作为一种新型的视频方式,其震撼效果是毋庸置疑的.目前市场上的VR全景视频也不在少数,越来越多的人能够欣赏到精彩的内容. 首先呢, VR内容场景的呈现分为两种情况: 1.实景拍摄 2.3D建 ...

  10. SQL端通过脚本判断文件夹是否存在 并创建

    做数据库备份作业的时候..想按日期建立文件夹.. 首先要判断文件夹是否存在 ) --路径 ) --日期 例如: 20171011 SET @DATE=CAST(DATEPART(YYYY,GETDAT ...