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

1模型创建

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

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

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

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

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

模型建立如下:

  1. from django.db import models
  2.  
  3. # Create your models here.
  4.  
  5. class Book(models.Model):
  6. id = models.AutoField(primary_key=True) # 可不填,Django会自动帮你写
  7. title = models.CharField(max_length=32)
  8. pub_date = models.DateField()
  9. price = models.DecimalField(max_digits=5, decimal_places=2)
  10. # 与Publish(id)建立一对多的外键关系
  11. publish = models.ForeignKey(to="Publish", to_field="id", on_delete=models.CASCADE)
  12. # 创建多对多的关系,不会添加外键,会另外创建表格
  13. authors = models.ManyToManyField(to="Author")
  14.  
  15. def __str__(self):
  16. return self.title
  17.  
  18. class Publish(models.Model):
  19. name = models.CharField(max_length=32)
  20. city = models.CharField(max_length=32)
  21. email = models.EmailField()
  22.  
  23. def __str__(self):
  24. return self.name
  25.  
  26. class Author(models.Model):
  27. name = models.CharField(max_length=32)
  28. age = models.IntegerField()
  29. # 与authorDetail建立一对一的外键关系
  30. authorDetail = models.OneToOneField(to="AuthorDetail", on_delete=models.CASCADE)
  31.  
  32. def __str__(self):
  33. return self.name
  34.  
  35. class AuthorDetail(models.Model):
  36. birthday = models.DateField()
  37. phone = models.BigIntegerField()
  38. addr = models.CharField(max_length=64)
  39.  
  40. def __str__(self):
  41. return self.addr
  42.  
  43. class Emp(models.Model):
  44. name = models.CharField(max_length=32)
  45. age = models.IntegerField()
  46. salary = models.DecimalField(max_digits=8, decimal_places=2)
  47. dep = models.CharField(max_length=32)
  48. province = models.CharField(max_length=32)
  49.  
  50. def __str__(self):
  51. return self.name
  52.  
  53. class Article(models.Model):
  54. title = models.CharField(max_length=32)
  55. comment_num = models.IntegerField()
  56. poll_num = models.IntegerField()
  57.  
  58. 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一对一以及一对多记录的创建:

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

  2.1.2 多对多记录的创建

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

2.2多表操作之跨表查询

2.2.1基于对象的跨表查询

  总的查询思路

  1. 基于对象的跨表查询( 子查询:以上一次的查询结果作为下一次的查询条件)
  2. (1)一对多
  3. 正向查询:按字段 book.publish
  4. Book对象 ---------------------------------- > Publish 对象
  5. <---------------------------------
  6. 反向查询:按表名小写_set.all()
  7.  
  8. (2)多对多
  9. 正向查询:按字段 book.authors.all()
  10. Book对象 ---------------------------------- > Author 对象
  11. <---------------------------------
  12. 反向查询:按表名小写_set.all()
  13.  
  14. (2)一对一
  15. 正向查询:按字段 book.ad
  16. Author 对象 ---------------------------------- > AuthorDetail 对象
  17. <---------------------------------
  18. 反向查询:按表名小写

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

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

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

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

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

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

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

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

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

  1. ################基于双下划线的跨表查询(join查询)##########################
  2. 1 查询PHP这本书籍的出版社的地址
  3. '''
  4. SELECT app01_publish.city from app01_book INNER JOIN app01_publish
  5. ON app01_book.publish_id = app01_publish.id
  6. WHERE app01_book.title ="PHP"
  7. '''
  8. 方式1
  9. queryset_addr = models.Book.objects.filter(title="PHP").values("publish__city")
  10. print(queryset_addr)
  11.  
  12. 方式2
  13. queryset_addr = models.Publish.objects.filter(book__title="PHP").values("city")
  14. print(queryset_addr)
  15.  
  16. 2 查询java书籍的所有作者
  17. queryset_author = models.Book.objects.filter(title="java").values("authors__name")
  18. queryset_author = models.Book.objects.filter(title__startswith="P").values("authors__name")
  19. print(queryset_author)
  20.  
  21. 3 查询唐马儒的手机号
  22. queryset_tel = models.Author.objects.filter(name="唐马儒").values("authorDetail__phone")
  23. queryset_tel = models.AuthorDetail.objects.filter(author__name="唐马儒").values("phone")
  24. print(queryset_tel)

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

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

2.2.3  聚合查询:

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

2.2.4  单表分组查询:

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

2.2.4  多表分组查询:

  1. ############## 多表分组查询 ###############
  2.  
  3. 1 查询每一个出版社的名字和出版过的书籍的平均价格
  4. querryset = models.Publish.objects.values("name").annotate(avg_salary=Avg("book__price"))
  5. querryset = models.Publish.objects.annotate(avg_salary=Avg("book__price")).values("name","avg_salary")
  6. print(querryset)
  7.  
  8. 2 查询每一个作者的名字以及出版书籍的个数
  9. querryset = models.Author.objects.values("name").annotate(c = Count("book__id"))
  10. querryset = models.Author.objects.annotate(c = Count("book__id")).values("name","c")
  11. print(querryset)
  12.  
  13. 3 查询每一个书籍的名称以及作者的个数
  14. querryset = models.Book.objects.values("title").annotate(c = Count("authors__id"))
  15. print(querryset)
  16.  
  17. 4 查询作者个数大于1 的每一本书籍的名称和作者个数
  18.  
  19. querryset = models.Book.objects.annotate(c = Count("authors__id")).filter(c__gt=1).values("title","c")
  20. print(querryset)
  21.  
  22. 5 查询书籍名称包含"h"的书籍名称和作者个数
  23. querryset = models.Book.objects.filter(title__contains="P").annotate(c = Count("authors__id")).values("title","c")
  24. querryset = models.Book.objects.annotate(c=Count("authors__id")).filter(title__contains="P").values("title", "c")
  25. print(querryset)

2.2.4  F与Q查询:

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

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

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

  1. ##################################### F查询与Q查询
  2.  
  3. F查询
  4. from django.db.models import F,Q,Avg
  5. 1 查询评论数大于100的文章
  6. ret = models.Article.objects.filter(comment_num__gt=300)
  7. print(ret)
  8.  
  9. 2 查询评论数大于点赞数的文章
  10. ret = models.Article.objects.filter(comment_num__gt=F("poll_num"))
  11. print(ret)
  12.  
  13. 3 查询评论数大于两倍点赞数
  14. ret = models.Article.objects.filter(comment_num__gt = F("poll_num")*2)
  15. print(ret)
  16.  
  17. 4 将所有的书籍的价格提高100
  18. ret = models.Book.objects.update(price = F("price")+10)
  19. print(ret)
  20.  
  21. Q查询
  22. 5 查询价格大于300或者名称以p开头的书籍
  23. Q : & | ~
  24. ret = models.Book.objects.filter(Q(price__gt=150)|Q(title__startswith="P"))
  25. print(ret)
  26.  
  27. # 5 查询价格大于300或者不是2012年2月份的书籍
  28. ret = models.Book.objects.filter(Q(price__gt=140) | Q(Q(pub_date__year=2012)&Q(pub_date__month=2)))
  29. ret = models.Book.objects.filter(Q(price__gt=140) | Q(pub_date__year=2012) & Q(pub_date__month=2))
  30. ret = models.Book.objects.filter(Q(price__gt=140) | Q(pub_date__year=2012,pub_date__month=2))
  31. 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. shell中的变量a=100, 什么时候作整数使用, 什么时候作字符串使用呢?

    shell中的变量a=100, 什么时候作整数使用, 什么时候作字符串使用呢? 这确实是一个困扰很久的一个问题? how it can be an issue? 事实上, 在shell中, 你可以认为 ...

  2. bzoj 3437 小p的农场

    bzoj 3437 小p的农场 思路 \(f[i]=min(f[j]+\sum\limits_{k=j+1}^{i}{b[k]*(i-k)}+a[i])\) \(f[i]=min(f[j]+\sum\ ...

  3. vs2015 + Python3.5 环境搭建

    1. vs2015只支持Python3.5及以前的版本,对应Anaconda3.4.2之前的版本. 2. 卸载掉所有安装过的Python 3. 建议重装VS2015, 因为增量升级Python Too ...

  4. hihoCoder week11 树中的最长路

    题目链接: https://hihocoder.com/contest/hiho11/problem/1 求树中节点对 距离最远的长度 #include <bits/stdc++.h> u ...

  5. nginx 配置 https 请求

    1,先去这个网站申请一下证书 https://certmall.trustauth.cn/Home/Member/index/id/1521167511.html 上面会教你怎么去做. 2,就是配置自 ...

  6. Microsoft.EntityFrameworkCore.Sqlite的学习

    SQLite in ASP.NET Core with EntityFrameworkCore ASP.NET Core 2: Using SQLite as a light weight datab ...

  7. NLog汇总

    相关文章 NLog文章系列——系列文章目录以及简要介绍 Elasticsearch,Kibana,Logstash,NLog实现ASP.NET Core 分布式日志系统 ElasticSearch+N ...

  8. EFI环境下的Ubuntu&Win10双系统安装

    因为是win10是EFI启动的,所以网上的easyBCD方法就不可以用了,这里用到的不是ultraiso软碟通,用的哪个忘了 不过只要能写入U盘做成启动盘就ok 具体参考的是https://blog. ...

  9. HashMap的实现原理-----哈希讲解

    哈希,英文名Hash.他就像是一个隔壁家的孩子一样,伴随着码工们的成长.听到他们的名字,我们都觉得很高大上. 在写程序的时候,一般我们都是这样被教育的:这个事情搞不定?用哈希呀! 在面试的时候,一般是 ...

  10. MySql查询功能梳理

    CREATE DATABASE CristinMysql Create table employee( eId int(9) not null auto_increment, eName varcha ...