ORM的多表创建(一对一.一对多,多对多):

1模型创建

  实例:我们来假定下面这些概念,字段和关系

作者模型:一个作者有姓名和年龄。

作者详细模型:把作者的详情放到详情表,包含生日,手机号,家庭住址等信息。作者详情模型和作者模型之间是一对一的关系(one-to-one)

出版商模型:出版商有名称,所在城市以及email。

书籍模型: 书籍有书名和出版日期,一本书可能会有多个作者,一个作者也可以写多本书,所以作者和书籍的关系就是多对多的关联关系(many-to-many);一本书只应该由一个出版商出版,所以出版商和书籍是一对多关联关系(one-to-many)。

模型建立如下:

from django.db import models

# Create your models here.

class Book(models.Model):
id = models.AutoField(primary_key=True) # 可不填,Django会自动帮你写
title = models.CharField(max_length=32)
pub_date = models.DateField()
price = models.DecimalField(max_digits=5, decimal_places=2)
# 与Publish(id)建立一对多的外键关系
publish = models.ForeignKey(to="Publish", to_field="id", on_delete=models.CASCADE)
# 创建多对多的关系,不会添加外键,会另外创建表格
authors = models.ManyToManyField(to="Author") def __str__(self):
return self.title class Publish(models.Model):
name = models.CharField(max_length=32)
city = models.CharField(max_length=32)
email = models.EmailField() def __str__(self):
return self.name class Author(models.Model):
name = models.CharField(max_length=32)
age = models.IntegerField()
# 与authorDetail建立一对一的外键关系
authorDetail = models.OneToOneField(to="AuthorDetail", on_delete=models.CASCADE) def __str__(self):
return self.name class AuthorDetail(models.Model):
birthday = models.DateField()
phone = models.BigIntegerField()
addr = models.CharField(max_length=64) def __str__(self):
return self.addr class Emp(models.Model):
name = models.CharField(max_length=32)
age = models.IntegerField()
salary = models.DecimalField(max_digits=8, decimal_places=2)
dep = models.CharField(max_length=32)
province = models.CharField(max_length=32) def __str__(self):
return self.name class Article(models.Model):
title = models.CharField(max_length=32)
comment_num = models.IntegerField()
poll_num = models.IntegerField() def __str__(self): return self.title

注意事项:

  • 表的名称myapp_modelName,是根据 模型中的元数据自动生成的,也可以覆写为别的名称  
  •  id 字段是自动添加的
  • 对于外键字段,Django 会在字段名上添加"_id" 来创建数据库中的列名
  • 这个例子中的CREATE TABLE SQL 语句使用PostgreSQL 语法格式,要注意的是Django 会根据settings 中指定的数据库类型来使用相应的SQL 语句。
  • 定义好模型之后,你需要告诉Django _使用_这些模型。你要做的就是修改配置文件中的INSTALL_APPSZ中设置,在其中添加models.py所在应用的名称。
  • 外键字段 ForeignKey 有一个 null=True 的设置(它允许外键接受空值 NULL),你可以赋给它空值 None 。

2.多表记录的操作

2.1 多表操作之表记录的创建

  2.1.1一对一以及一对多记录的创建:

  方式一
book = models.Book.objects.create(title="java",price=122,pub_date="2012-02-12",publish_id=1) 方式二
pub_obj = models.Publish.objects.filter(name="西瓜出版社").first()
book = models.Book.objects.create(title="PHP", price=122, pub_date="2014-02-12", publish = pub_obj)
print(book.title)
print(book.publish_id)

  2.1.2 多对多记录的创建

 ######################### 绑定多对多的关系;无非是在关系表创建记录 ##########################
tips: 正向操作按字段,反向操作按表名小写(一定要记住) 为java这本书绑定两个作者: 大锤,尼玛(正向绑定):
添加方式一
java = models.Book.objects.filter(title="java").first()
dachui = models.Author.objects.filter(name="王大锤").first()
nima = models.Author.objects.filter(name="王尼玛").first()
print(java.price)
print(dachui.name)
print(nima.name)
java.authors.add(dachui,nima) 添加方式二
java.authors.add(2)
java.authors.add(*[3,2]) #添加的另外一种方式,较常用,[]内为对应作者的ID,*用于打散 移除两个作者与java的绑定关系
java.authors.remove(dachui, nima) # 将某个特定的对象从被关联对象集合中去除。== book_obj.authors.remove(*[]) java.authors.clear() #清空被关联对象集合 重新赋值关系
java.authors.set([3,]) #重新设置值,先clear,在赋值 给王大锤作者绑定两本书籍: PHP,Go(反向绑定)
dachui = models.Author.objects.filter(name="王大锤").first()
PHP = models.Book.objects.filter(title="PHP").first()
Go = models.Book.objects.filter(title="Go").first()
方式一:
dachui.book_set.add(PHP, Go) ###此处因为是反向绑定采用的是 表名_set
方式二
dachui.book_set.add(*[3,4])

2.2多表操作之跨表查询

2.2.1基于对象的跨表查询

  总的查询思路

  一 基于对象的跨表查询( 子查询:以上一次的查询结果作为下一次的查询条件)
(1)一对多
正向查询:按字段 book.publish
Book对象 ---------------------------------- > Publish 对象
<---------------------------------
反向查询:按表名小写_set.all() (2)多对多
正向查询:按字段 book.authors.all()
Book对象 ---------------------------------- > Author 对象
<---------------------------------
反向查询:按表名小写_set.all() (2)一对一
正向查询:按字段 book.ad
Author 对象 ---------------------------------- > AuthorDetail 对象
<---------------------------------
反向查询:按表名小写

  2.2.1.1 基于对象的一对多的跨表查询

(1)一对多

    1 查询PHP这本书籍的出版社的地址(正向查询)
addr = models.Book.objects.filter(title="PHP").first().publish.city
print(addr) 2 查询香蕉出版社出版的所有书籍(反向查询)
queryset = models.Publish.objects.filter(name="西瓜出版社").first().book_set.all()
print(queryset)

  2.2.1.2 基于对象的多对多的跨表查询

 (2)多对多

    1 查询java书籍的所有作者
queryset = models.Book.objects.filter(title="java").first().authors.all()
print(queryset) 2 查询王大锤作者出版过得所有书籍
queryset = models.Author.objects.filter(name="王大锤").first().book_set.all()
print(queryset)

  2.2.1.3 基于对象的一对一的跨表查询

(3)一对一
1 查询王大锤的手机号
phone = models.Author.objects.filter(name="王大锤").first().authorDetail.phone
print(phone) 2 查询手机号为123的作者的名字
name = models.AuthorDetail.objects.filter(phone="").first().author.name
print(name)

2.2.2  基于双下划綫的跨表查询:

KEY: 通知ORM引擎如何跨表: 正向查询按字段, 反向查询按表名小写

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

 ################基于双下划线的跨表查询(join查询)##########################
1 查询PHP这本书籍的出版社的地址
'''
SELECT app01_publish.city from app01_book INNER JOIN app01_publish
ON app01_book.publish_id = app01_publish.id
WHERE app01_book.title ="PHP"
'''
方式1
queryset_addr = models.Book.objects.filter(title="PHP").values("publish__city")
print(queryset_addr) 方式2
queryset_addr = models.Publish.objects.filter(book__title="PHP").values("city")
print(queryset_addr) 2 查询java书籍的所有作者
queryset_author = models.Book.objects.filter(title="java").values("authors__name")
queryset_author = models.Book.objects.filter(title__startswith="P").values("authors__name")
print(queryset_author) 3 查询唐马儒的手机号
queryset_tel = models.Author.objects.filter(name="唐马儒").values("authorDetail__phone")
queryset_tel = models.AuthorDetail.objects.filter(author__name="唐马儒").values("phone")
print(queryset_tel)

2.2.2.2 连续跨表操作及其示例:

连续跨表
4 查询西瓜出版社出版过的所有书籍的名字以及作者的姓名
queryset_info = models.Book.objects.filter(publish__name="西瓜出版社").values("title","authors__name")
queryset_info = models.Author.objects.filter(book__publish__name="西瓜出版社").values("book__title","name")
print(queryset_info) 5 手机号以151开头的作者出版过的所有书籍名称以及出版社名称
queryset_info = models.Book.objects.filter(authors__authorDetail__phone__startswith="").values("title","publish__name")
print(queryset_info

2.2.3  聚合查询:

 ######################聚合查询#############################3
aggregate() from django.db.models import Avg,Max,Min,Count
1.计算所有人的平均工资
ret = models.Emp.objects.all().aggregate(平均工资=Avg("salary"))
print(re

2.2.4  单表分组查询:

    ############## 单表分组查询  ###############
查询每一个部门的人数
ret = models.Emp.objects.values("dep").annotate(Count("id")) 查询省份名字有东的部门的人数
ret = models.Emp.objects.filter(province__contains="东").values("dep").annotate(c = Count("id"))
print(ret) # 查询每一个省份的平均薪水
ret = models.Emp.objects.values("province").annotate(avg_salary=Avg("salary"))
print(ret)

2.2.4  多表分组查询:

############## 多表分组查询  ###############

    1 查询每一个出版社的名字和出版过的书籍的平均价格
querryset = models.Publish.objects.values("name").annotate(avg_salary=Avg("book__price"))
querryset = models.Publish.objects.annotate(avg_salary=Avg("book__price")).values("name","avg_salary")
print(querryset) 2 查询每一个作者的名字以及出版书籍的个数
querryset = models.Author.objects.values("name").annotate(c = Count("book__id"))
querryset = models.Author.objects.annotate(c = Count("book__id")).values("name","c")
print(querryset) 3 查询每一个书籍的名称以及作者的个数
querryset = models.Book.objects.values("title").annotate(c = Count("authors__id"))
print(querryset) 4 查询作者个数大于1 的每一本书籍的名称和作者个数 querryset = models.Book.objects.annotate(c = Count("authors__id")).filter(c__gt=1).values("title","c")
print(querryset) 5 查询书籍名称包含"h"的书籍名称和作者个数
querryset = models.Book.objects.filter(title__contains="P").annotate(c = Count("authors__id")).values("title","c")
querryset = models.Book.objects.annotate(c=Count("authors__id")).filter(title__contains="P").values("title", "c")
print(querryset)

2.2.4  F与Q查询:

F查询: 在上面所有的例子中,我们构造的过滤器都只是将字段值与某个常量做比较。如果我们要对两个字段的值做比较,那该怎么做呢?

Django 提供 F() 来做这样的比较。F() 的实例可以在查询中引用字段,来比较同一个 model 实例中两个不同字段的值。

Q查询:filter() 等方法中的关键字参数查询都是一起进行“AND” 的。 如果你需要执行更复杂的查询(例如OR 语句),你可以使用Q对象

##################################### F查询与Q查询

     F查询
from django.db.models import F,Q,Avg
1 查询评论数大于100的文章
ret = models.Article.objects.filter(comment_num__gt=300)
print(ret) 2 查询评论数大于点赞数的文章
ret = models.Article.objects.filter(comment_num__gt=F("poll_num"))
print(ret) 3 查询评论数大于两倍点赞数
ret = models.Article.objects.filter(comment_num__gt = F("poll_num")*2)
print(ret) 4 将所有的书籍的价格提高100元
ret = models.Book.objects.update(price = F("price")+10)
print(ret) Q查询
5 查询价格大于300或者名称以p开头的书籍
Q : & | ~
ret = models.Book.objects.filter(Q(price__gt=150)|Q(title__startswith="P"))
print(ret) # 5 查询价格大于300或者不是2012年2月份的书籍
ret = models.Book.objects.filter(Q(price__gt=140) | Q(Q(pub_date__year=2012)&Q(pub_date__month=2)))
ret = models.Book.objects.filter(Q(price__gt=140) | Q(pub_date__year=2012) & Q(pub_date__month=2))
ret = models.Book.objects.filter(Q(price__gt=140) | Q(pub_date__year=2012,pub_date__month=2))
print(ret)

详细请参考:ORM多表查询

Django中模型层中ORM的多表操作的更多相关文章

  1. Django之模型层第一篇:单表操作

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

  2. Django之模型层第二篇:多表操作

    Django之模型层第二篇:多表操作 一 表关系回顾 ​ 在讲解MySQL时,我们提到,把应用程序的所有数据都放在一张表里是极不合理的. ​ 比如我们开发一个员工管理系统,在数据库里只创建一张员工信息 ...

  3. Django的模型层(1)- 单表操作(上)

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

  4. Django的模型层(2) - 多表操作(下)

    一.多表查询 1.基于双下划线的跨表查询 Django 还提供了一种直观而高效的方式在查询(lookups)中表示关联关系,它能自动确认 SQL JOIN 联系.要做跨关系查询,就使用两个下划线来链接 ...

  5. 6、Django之模型层第一篇:单表操作

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

  6. 7、Django之模型层第二篇:多表操作

    一 表关系回顾 在讲解MySQL时,我们提到,把应用程序的所有数据都放在一张表里是极不合理的. 比如我们开发一个员工管理系统,在数据库里只创建一张员工信息表,该表有四个字段:工号.姓名.部门名.部门职 ...

  7. Django的模型层(2)- 多表操作(上)

    一.创建模型 例:我们来假定下面这些概念,字段和关系 作者模型:一个作者有姓名和年龄. 作者详细模型:把作者的详情放到详情表,包含生日,手机号,家庭住址等信息.作者详情模型和作者模型之间是一对一(on ...

  8. Django的模型层(1)- 单表操作(下)

    一.查询表记录 在学习查询表记录之前,先了解一下QuerySet,这是一种类似列表的数据类型,是由ORM创建的.我们学习查询表记录的方法时,一定要明确哪些方法返回了QuerySet类型,哪些方法返回m ...

  9. Django中模型层中ORM的单表操作

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

  10. 64、django之模型层(model)--建表、查询、删除基础

    要说一个项目最重要的部分是什么那铁定数据了,也就是数据库,这篇就开始带大家走进django关于模型层model的使用,model主要就是操纵数据库不使用sql语句的情况下完成数据库的增删改查.本篇仅带 ...

随机推荐

  1. vscode Git:failed to execute git

    在vscoad中选择全部提交时候提示 Git:failed to execute git在git日志中会看到这么一行错误信息 empty ident name (for <XXXXXX.com& ...

  2. P4777 【模板】扩展中国剩余定理(EXCRT)

    思路 中国剩余定理解决的是这样的问题 求x满足 \[ \begin{matrix}x \equiv a_1(mod\ m_1)\\x\equiv a_2(mod\ m_2)\\ \dots\\x\eq ...

  3. 以结算价交易TAS和以市价交易TAM

    CME Group的合约规格中提到TAS和TAM交易,如:Gold Futures Contract Specs Gold 期货 合约规格 Trading at Settlement (TAS) is ...

  4. CentOS7时间和日期的同步 (chrony和)

    CentOS 6版本,使用 hwclock CentOS 7版本,使用timedatectl 1.基本概念 1.1 GMT,UTC,CST,DST时间 世界标准时间 整个地球分为二十四时区,每个时区都 ...

  5. HDU 5985 Lucky Coins(概率)

    http://acm.split.hdu.edu.cn/showproblem.php?pid=5985 题意:有多种类型的硬币,每种类型的硬币都有一定的数量,现在每次抛硬币,除去朝下的硬币,知道最后 ...

  6. BZOJ 1070: [SCOI2007]修车(费用流)

    http://www.lydsy.com/JudgeOnline/problem.php?id=1070 题意: 思路: 神奇的构图. 因为排在后面的人需要等待前面的车修好,这里将每个技术人员拆成n个 ...

  7. CSS属性大全

    字体属性:(font)大小 font-size:x-large;(特大) xx-small;(极小) 一般中文用不到,只要用数值就可以,单位:PX.PD样式 font-style:oblique;(偏 ...

  8. JAVA之经典算法

    package Set.Java.algorithm; import java.util.Scanner; public class algorithm { /** * [程序1] 题目:古典问题:有 ...

  9. List<Model>转String 、String 转List<string>

    var ltCode = from item in psw.VehicleInsuranceItem select item.Code; string code = string.Join(" ...

  10. SSH KEY 设置 目录在open ~ 根目录下的.ssh 里面

    当我们从github或者gitlab上clone项目或者参与项目时,需要证明我们的身份.github.gitlab支持使用SSH协议进行免密登录,而SSH协议采用了RSA算法保证了登录的安全性.我们要 ...