Django中模型层中ORM的多表操作

2023-10-19 08:30

本文主要是介绍Django中模型层中ORM的多表操作,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

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.titleclass Publish(models.Model):name = models.CharField(max_length=32)city = models.CharField(max_length=32)email = models.EmailField()def __str__(self):return self.nameclass 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.nameclass AuthorDetail(models.Model):birthday = models.DateField()phone = models.BigIntegerField()addr = models.CharField(max_length=64)def __str__(self):return self.addrclass 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.nameclass Article(models.Model):title = models.CharField(max_length=32)comment_num = models.IntegerField()poll_num = models.IntegerField()def __str__(self): return self.title
View Code

注意事项:

  •  表的名称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)
View Code

  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])
View Code

 

2.2多表操作之跨表查询

 

2.2.1基于对象的跨表查询

  总的查询思路

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

 

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

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

  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)
View Code

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

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

 

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"'''
方式1queryset_addr = models.Book.objects.filter(title="PHP").values("publish__city")print(queryset_addr)方式2queryset_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)
View Code

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="1").values("title","publish__name")print(queryset_info
View Code

 

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  单表分组查询:
    ############## 单表分组查询  ###############
查询每一个部门的人数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,Avg1 查询评论数大于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)
View Code

 

详细请参考:ORM多表查询

 

 

转载于:https://www.cnblogs.com/Mixtea/p/10469839.html

这篇关于Django中模型层中ORM的多表操作的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/238618

相关文章

Python调用Orator ORM进行数据库操作

《Python调用OratorORM进行数据库操作》OratorORM是一个功能丰富且灵活的PythonORM库,旨在简化数据库操作,它支持多种数据库并提供了简洁且直观的API,下面我们就... 目录Orator ORM 主要特点安装使用示例总结Orator ORM 是一个功能丰富且灵活的 python O

python使用fastapi实现多语言国际化的操作指南

《python使用fastapi实现多语言国际化的操作指南》本文介绍了使用Python和FastAPI实现多语言国际化的操作指南,包括多语言架构技术栈、翻译管理、前端本地化、语言切换机制以及常见陷阱和... 目录多语言国际化实现指南项目多语言架构技术栈目录结构翻译工作流1. 翻译数据存储2. 翻译生成脚本

0基础租个硬件玩deepseek,蓝耘元生代智算云|本地部署DeepSeek R1模型的操作流程

《0基础租个硬件玩deepseek,蓝耘元生代智算云|本地部署DeepSeekR1模型的操作流程》DeepSeekR1模型凭借其强大的自然语言处理能力,在未来具有广阔的应用前景,有望在多个领域发... 目录0基础租个硬件玩deepseek,蓝耘元生代智算云|本地部署DeepSeek R1模型,3步搞定一个应

Deepseek R1模型本地化部署+API接口调用详细教程(释放AI生产力)

《DeepseekR1模型本地化部署+API接口调用详细教程(释放AI生产力)》本文介绍了本地部署DeepSeekR1模型和通过API调用将其集成到VSCode中的过程,作者详细步骤展示了如何下载和... 目录前言一、deepseek R1模型与chatGPT o1系列模型对比二、本地部署步骤1.安装oll

Spring AI Alibaba接入大模型时的依赖问题小结

《SpringAIAlibaba接入大模型时的依赖问题小结》文章介绍了如何在pom.xml文件中配置SpringAIAlibaba依赖,并提供了一个示例pom.xml文件,同时,建议将Maven仓... 目录(一)pom.XML文件:(二)application.yml配置文件(一)pom.xml文件:首

轻松上手MYSQL之JSON函数实现高效数据查询与操作

《轻松上手MYSQL之JSON函数实现高效数据查询与操作》:本文主要介绍轻松上手MYSQL之JSON函数实现高效数据查询与操作的相关资料,MySQL提供了多个JSON函数,用于处理和查询JSON数... 目录一、jsON_EXTRACT 提取指定数据二、JSON_UNQUOTE 取消双引号三、JSON_KE

C++实现封装的顺序表的操作与实践

《C++实现封装的顺序表的操作与实践》在程序设计中,顺序表是一种常见的线性数据结构,通常用于存储具有固定顺序的元素,与链表不同,顺序表中的元素是连续存储的,因此访问速度较快,但插入和删除操作的效率可能... 目录一、顺序表的基本概念二、顺序表类的设计1. 顺序表类的成员变量2. 构造函数和析构函数三、顺序表

使用C++实现单链表的操作与实践

《使用C++实现单链表的操作与实践》在程序设计中,链表是一种常见的数据结构,特别是在动态数据管理、频繁插入和删除元素的场景中,链表相比于数组,具有更高的灵活性和高效性,尤其是在需要频繁修改数据结构的应... 目录一、单链表的基本概念二、单链表类的设计1. 节点的定义2. 链表的类定义三、单链表的操作实现四、

如何在本地部署 DeepSeek Janus Pro 文生图大模型

《如何在本地部署DeepSeekJanusPro文生图大模型》DeepSeekJanusPro模型在本地成功部署,支持图片理解和文生图功能,通过Gradio界面进行交互,展示了其强大的多模态处... 目录什么是 Janus Pro1. 安装 conda2. 创建 python 虚拟环境3. 克隆 janus

Python利用自带模块实现屏幕像素高效操作

《Python利用自带模块实现屏幕像素高效操作》这篇文章主要为大家详细介绍了Python如何利用自带模块实现屏幕像素高效操作,文中的示例代码讲解详,感兴趣的小伙伴可以跟随小编一起学习一下... 目录1、获取屏幕放缩比例2、获取屏幕指定坐标处像素颜色3、一个简单的使用案例4、总结1、获取屏幕放缩比例from