千家信息网

如何进行ORM多表操作

发表于:2026-11-04 作者:千家信息网编辑
千家信息网最后更新 2026年11月04日,本篇文章为大家展示了如何进行ORM多表操作,内容简明扼要并且容易理解,绝对能使你眼前一亮,通过这篇文章的详细介绍希望你能有所收获。1.建表from django.db import models# C
千家信息网最后更新 2026年11月04日如何进行ORM多表操作

本篇文章为大家展示了如何进行ORM多表操作,内容简明扼要并且容易理解,绝对能使你眼前一亮,通过这篇文章的详细介绍希望你能有所收获。

1.建表

from django.db import models# Create your models here.class AuthorDtail(models.Model):    nid = models.AutoField(primary_key=True)    birthday = models.DateField()    telephone = models.BigIntegerField()    addr = models.CharField(max_length=64)class Author(models.Model):    nid = models.AutoField(primary_key=True)    name = models.CharField(max_length=32)    age = models.IntegerField()    # OneToOneField可以建立在两个模型中的任意一个    authorDetail = models.OneToOneField(to="AuthorDtail", to_field="nid", on_delete=models.CASCADE)class Publish(models.Model):    nid = models.AutoField(primary_key=True)    name = models.CharField(max_length=32)    city = models.CharField(max_length=32)    email = models.EmailField()class Book(models.Model):    nid = models.AutoField(primary_key=True)    title = models.CharField(max_length=32)    publishDate = models.DateField()    price = models.DecimalField(max_digits=9,decimal_places=2)    # 与Publish建立一对多的关系,外键字段建立在多的一方    publish = models.ForeignKey(to="Publish", to_field="nid", on_delete=models.CASCADE)    # 多对多,ManyToManyField可以建在两个模型中的任意一个,自动创建第三张表    authors = models.ManyToManyField(to="Author")




MySQL查看建表语句

CREATE TABLE `app1_authordetail` (  `nid` int(11) NOT NULL AUTO_INCREMENT,  `birthday` date NOT NULL,  `telephone` bigint(20) NOT NULL,  `addr` varchar(64) NOT NULL,  PRIMARY KEY (`nid`)) ENGINE=InnoDB DEFAULT CHARSET=utf8;#UNIQUE KEY `authorDetail_id` (`authorDetail_id`),这是OneToOneField创建的。CREATE TABLE `app1_author` (  `nid` int(11) NOT NULL AUTO_INCREMENT,  `name` varchar(32) NOT NULL,  `age` int(11) NOT NULL,  `authorDetail_id` int(11) NOT NULL,  PRIMARY KEY (`nid`),  UNIQUE KEY `authorDetail_id` (`authorDetail_id`),  CONSTRAINT `app1_author_authorDetail_id_d894fd2a_fk_app1_authordetail_nid` FOREIGN KEY (`authorDetail_id`) REFERENCES `app1_authordetail` (`nid`)) ENGINE=InnoDB DEFAULT CHARSET=utf8;CREATE TABLE `app1_publish` (  `nid` int(11) NOT NULL AUTO_INCREMENT,  `name` varchar(32) NOT NULL,  `city` varchar(32) NOT NULL,  `email` varchar(254) NOT NULL,  PRIMARY KEY (`nid`)) ENGINE=InnoDB DEFAULT CHARSET=utf8;CREATE TABLE `app1_book` (  `nid` int(11) NOT NULL AUTO_INCREMENT,  `title` varchar(32) NOT NULL,  `publishDate` date NOT NULL,  `price` decimal(9,2) NOT NULL,  `publish_id` int(11) NOT NULL,  PRIMARY KEY (`nid`),  KEY `app1_book_publish_id_e41ee7e4` (`publish_id`),  CONSTRAINT `app1_book_publish_id_e41ee7e4_fk_app1_publish_nid` FOREIGN KEY (`publish_id`) REFERENCES `app1_publish` (`nid`)) ENGINE=InnoDB DEFAULT CHARSET=utf8;#ManyToManyField创建的第三方表CREATE TABLE `app1_book_authors` (  `id` int(11) NOT NULL AUTO_INCREMENT,  `book_id` int(11) NOT NULL,  `author_id` int(11) NOT NULL,  PRIMARY KEY (`id`),  UNIQUE KEY `app1_book_authors_book_id_author_id_ce887e61_uniq` (`book_id`,`author_id`),  KEY `app1_book_authors_author_id_89b9ee26_fk_app1_author_nid` (`author_id`),  CONSTRAINT `app1_book_authors_author_id_89b9ee26_fk_app1_author_nid` FOREIGN KEY (`author_id`) REFERENCES `app1_author` (`nid`),  CONSTRAINT `app1_book_authors_book_id_75b281cd_fk_app1_book_nid` FOREIGN KEY (`book_id`) REFERENCES `app1_book` (`nid`)) ENGINE=InnoDB DEFAULT CHARSET=utf8;
1.表的名称是app_modelName,是根据模型中的元数据自动生成的,也可以重写为别的名称。2.如果没有定义AutoField(),默认会创建id字段,为主键。3.对于外键字段,Django会在字段上添加"_id"来设置列名。4.Django会根据settings中指定的数据库类型来使用相应的SQL语句。5.要在INSTALL_APPS中设置models.py所在的应用名称6.外键字段 ForeignKey 有一个 null=True 的设置(它允许外键接受空值 NULL),你可以赋给它空值 None 。

2.多表ORM的增删改查

2.1插入数据

2.1.1一对多插入数据

from django.shortcuts import renderfrom app1.models import *def index(request):    # 注意:这里一定要是一个model对象,不能是queryset对象    # 方式一:设置publish,是一个Model对象。    publish_obj = Publish.objects.get(nid=1)    aa_book_obj = Book.objects.create(title="AA_title",publishDate="2012-12-12",price=100,publish=publish_obj)    # 方式二:设置publish_id    bb_book_obj = Book.objects.create(title="BB_title", publishDate="2012-12-12", price=100, publish_id=2)    print(aa_book_obj.title)    print(aa_book_obj.publish.name)    print(bb_book_obj.title)    print(bb_book_obj.publish.name)    # 这里关键在于publish与publish_id的区别。    # 可以发现,    # publish是一个对象,可以通过publish调用相应Publish表中的字段数据    # publish_id只是Book表中的一个字段值    print(bb_book_obj.publish.nid)    print(bb_book_obj.publish_id)    return render(request, "index.html")
查询title为AA_title的出版社邮箱book_obj=Book.objects.filter(title="AA_title").first() print(book_obj.publish.email)

2.1.2多对多插入数据

from django.shortcuts import renderfrom app1.models import *def index(request):    # 绑定多对多关系    cc_book_obj = Book.objects.create(title="CC_title",publishDate="2018-12-12",price=120,publish_id=1)    vita = Author.objects.get(name="vita")    lili = Author.objects.get(name="lili")    # 方式一:add-author对象    cc_book_obj.authors.add(vita,lili)    # 方式二:add-author_id    dd_book_obj = Book.objects.create(title="DD_title",publishDate="2018-12-12",price=120,publish_id=1)    dd_book_obj.authors.add(1,2)    # 方式三:add-*[1,2,3]    ee_book_obj = Book.objects.create(title="EE_title", publishDate="2018-12-12", price=120, publish_id=1)    ee_book_obj.authors.add(*[1,2])    return render(request, "index.html")

2.1.3多对多的关键点

from django.shortcuts import renderfrom app1.models import *def index(request):    ee_book_obj = Book.objects.filter(title="EE_title").first()    # 关键点:ee_book_obj.authors.all()    # 与本书关联的所有作者信息集合,是queryset对象    # , ]>    print(ee_book_obj.authors.all())    return render(request, "index.html")

2.1.4多对多解除绑定

book_obj.authors.remove()      # 将某个特定的对象从被关联对象集合中去除。    ======   book_obj.authors.remove(*[])book_obj.authors.clear()       #清空被关联对象集合book_obj.authors.set()         #先清空再设置
from django.shortcuts import renderfrom app1.models import *def index(request):    vita = Author.objects.filter(name="vita").first()    aa_book_obj = Book.objects.filter(title="CC_title").first()    # 方式一:remove-author对象    aa_book_obj.authors.remove(vita)    # 方式二:remove-author的nid    aa_book_obj.authors.remove(2)    bb_book_obj = Book.objects.filter(title="DD_title").first()    # 方式三:remove-*[1,2]    bb_book_obj.authors.remove(*[1,2])    return render(request, "index.html")

2.2跨表查询

1 基于对象查询2 基于双下划线查询3 聚合和分组查询4 F 与 Q查询

2.2.1正向查询与反向查询

一对多关系中,models.ForeignKey设置在book中,根据book表查询author信息,是正向查询根据author表查询book信息,是反向查询多对多关系中,models.ManyToMany设置在book表中,根据book表查询author信息,是正向查询根据author表查询book信息,是反向查询一对一关系中,models.OneToOne设置在author表中,根据author表查询authoDetail信息,是正向查询根据authorDetail表查询quthor信息,是反向查询守则:正想查询按字段反向查询按表名详解:正向查询按字段,models.py中设置的关联字段,即Author类中的authorDetail,Book类中的publish和author。(一对多,多对多)反向查询按表名小写_set----因为是多个数据,所以使用set,集合之意。(一对一)反向查询按表名小写----因为只有一条对应数据,所以无set。

2.2.2基于对象查询----子查询

守则:正想查询按字段反向查询按表名详解:正向查询按字段,models.py中设置的关联字段,即Author类中的authorDetail,Book类中的publish和author。(一对多,多对多)反向查询按表名小写_set----因为是多个数据,所以使用set,集合之意。(一对一)反向查询按表名小写----因为只有一条对应数据,所以无set。
2.2.2.1准备数据




2.2.2.2基于对象查询--一对多查询
from django.shortcuts import renderfrom app1.models import *def index(request):    # 一对多的正向查询:查询三国演义这本书的出版社名字    # 一本书只对应一个出版社,返回值是一个model对象    publish_obj = Book.objects.filter(title="SanGuo").first().publish    print(publish_obj)  # Publish object (1)    print(publish_obj.name)  # AA出版社    # SQL语句:    # 一对多的反向查询:查询 AA_出版社 出版过的书籍名称    # 一个出版社对应多本书,返回值是一个queryset集合    book_list = Publish.objects.filter(name="AA_publish").first().book_set.all()    print(book_list)  # , , , ]>    # SQL语句:    return render(request, "index.html")

2.2.2.3基于对象查询--多对多查询
from django.shortcuts import renderfrom app1.models import *def index(request):    # 多对多正向查询:查询Sanguo这本书的所有作者名字    # 书和作者是多对多关系,返回值是queryset集合。    # , ]>    author_list = Book.objects.filter(title="SanGuo").first().authors.all()    print(author_list)    # 多对多反向查询:查询vita出版过的所有书籍名称    # 书和作者是多对多关系,返回值是queryset集合。    # , , , , ]>    book_list = Author.objects.filter(name="vita").first().book_set.all()    print(book_list)    return render(request, "index.html")

2.2.2.4基于对象查询--一对一查询
from django.shortcuts import renderfrom app1.models import *def index(request):    # 一对一的正向查询:查询vita的手机号    # 一对一关系,返回值是model对象    # AuthorDetail object (1)    author_detail_obj = Author.objects.filter(name="vita").first().authorDetail    print(author_detail_obj)    # 一对一的反向查询:查询手机号为112233的作者    # 一对一关系,返回值是model对象    # Author object (1)    author_obj = AuthorDetail.objects.filter(telephone="112233").first().author    print(author_obj)    return render(request, "index.html")

2.2.3基于双下划线的跨表查询----join查询

守则:正想查询按字段反向查询按表名
2.2.3.1基于双下划线的跨表查询--一对多查询
from django.shortcuts import renderfrom app1.models import *def index(request):    # 一对多查询:查询SanGuo这本书的出版社名字    # 返回值是queryset对象    # 方式一正向查询:    ret = Book.objects.filter(title="SanGuo").values("publish__name")    print(ret)  #     # 方式二反向查询:    ret2 = Publish.objects.filter(book__title="SanGuo").values("name")    print(ret2)  #     # 一对多查询:查询 AA_publish出版社出版的书籍名称    # 返回值是queryset对象    # 方式一正向查询:    ret3 = Publish.objects.filter(name="AA_publish").values("book__title")    print(ret3)  #     # 方式二反向查询:    ret4 = Book.objects.filter(publish__name="AA_publish").values("title")    print(ret4)  #     return render(request, "index.html")

2.2.3.2基于双下划线的跨表查询--多对多查询
from django.shortcuts import renderfrom app1.models import *def index(request):    # 多对多查询:查询SanGuo这本书的所有作者的名字    # 返回值:queryset对象    # 方式一:正向查询    ret1 = Book.objects.filter(title="SanGuo").values("authors__name")    print(ret1)  #     # 方式二:反向查询    ret2 = Author.objects.filter(book__title="SanGuo").values("name")    print(ret2)  #     return render(request, "index.html")

2.2.3.3基于双下划线的跨表查询--一对一查询
from django.shortcuts import renderfrom app1.models import *def index(request):    # 一对一查询:查询vita的手机号    # 返回值queryset对象    # 方式一:正向查询    ret1 = Author.objects.filter(name="vita").values("authorDetail__telephone")    print(ret1)  #     # 方式二:反向查询    ret2 = AuthorDetail.objects.filter(author__name="vita").values("telephone")    print(ret2)  #     return render(request, "index.html")

2.2.3.4基于双下划线的跨多表查询
from django.shortcuts import renderfrom app1.models import *def index(request):    # 手机号以11开头的作者出版过的书籍名称以及出版社的名称    ret1 = Author.objects.filter(authorDetail__telephone__startswith="11").values("book__title","book__publish__name")    print(ret1)    ret2 = AuthorDetail.objects.filter(telephone__startswith="11").values("author__book__title","author__book__publish__name")    print(ret2)    ret3 = Book.objects.filter(authors__authorDetail__telephone__startswith="11").values("title","publish__name")    print(ret3)    return render(request, "index.html")

2.2.4聚合与分组查询

2.2.4.1aggregate聚合查询
返回值是字典
from django.shortcuts import renderfrom django.db.models import Avg,Max,Min,Countfrom app1.models import *def index(request):    # 查询所有书籍的平均价格    # 返回值是字典    ret = Book.objects.filter(publishDate__year=2012).aggregate(avg_price=Avg("price"),max_price=Max("price"),min_price=Min("price"))    print(ret)  # {'avg_price': Decimal('100.000000'), 'max_price': Decimal('100.00'), 'min_price': Decimal('100.00')}    return render(request, "index.html")

2.2.4.2annotate分组查询--单表分组
# annotate分组查询# 单表分组查询的ORM语法: 单表模型.objects.values("group by的字段").annotate(聚合函数("统计字段"))# 返回值为queryset对象# 补充知识点:    #    # ret=Emp.objects.all()    # print(ret)  # select * from emp    # ret=Emp.objects.values("name")    # print(ret)  # select name from emp    # 单表下按照id分组,没有任何意义,这里all()就包含了所有字段,包含了主键id,id是唯一的,按照该字段分组没有任何意义    # Emp.objects.all().annotate(avg_salary=Avg("salary"))
from django.shortcuts import renderfrom django.db.models import Avg,Max,Min,Countfrom app1.models import *def index(request):    # 查询每种价格的书的价格和数量    # ret = Book.objects.values("price").annotate(book_count = Count("nid").values("title")    # 单表分组时,最后加values()是又加了一个分组字段,不是取出字段值    ret = Book.objects.values("price").annotate(book_count = Count("nid"))    print(ret)  #     return render(request, "index.html")

2.2.4.3annotate分组查询--多表分组
from django.shortcuts import renderfrom django.db.models import Avg,Max,Min,Countfrom app1.models import *def index(request):    # 查询每一个出版社的名称以及出版的书籍数    # 反向查询    ret1 = Publish.objects.values("name").annotate(book_count=Count("book__nid"))    print(ret1) #     # 正向查询    ret2 = Book.objects.values("publish__name").annotate(book_count=Count("nid"))    print(ret2) #     # 正向查询,最后values取值    ret3 = Book.objects.values("publish__nid").annotate(book_count=Count("nid")).values("publish__name","book_count")    print(ret3) #     return render(request, "index.html")

from django.shortcuts import renderfrom django.db.models import Avg,Max,Min,Countfrom app1.models import *def index(request):    # 总结 跨表的分组查询的模型:    # 每一个后表模型.objects.values("pk").annotate(聚合函数(关联表__统计字段))    # pk为主键    # 1.查询每一个作者的名字以及出版过的书籍的最高价格    ret1 = Author.objects.values("pk").annotate(max_price = Max("book__price")).values("name","max_price")    print(ret1)    # 2.查询每一个书籍的名称以及对应的作者数    ret2 = Book.objects.values("pk").annotate(author_count = Count("authors__nid")).values("title","author_count")    print(ret2)    return render(request, "index.html")

from django.shortcuts import renderfrom django.db.models import Avg,Max,Min,Countfrom app1.models import *def index(request):    # 查询每一个出版社的名称以及出版社的书籍个数    # 三种方式:    ret1=Publish.objects.values("nid").annotate(c=Count("book__title")).values("name","email","c")    print(ret1)    ret2=Publish.objects.all().annotate(c=Count("book__title")).values("name","c","city")    print(ret2)    ret3 = Publish.objects.annotate(c=Count("book__title")).values("name", "c", "city")    print(ret3)    return render(request, "index.html")

from django.shortcuts import renderfrom django.db.models import Avg,Max,Min,Countfrom app1.models import *def index(request):    # 统计每一本以S开头的书籍的作者个数    ret1 = Book.objects.filter(title__startswith="S").values("pk").annotate(author_count = Count("authors__nid")).values("title","author_count")    print(ret1)    # 统计不止一个作者的图书    ret2 = Book.objects.values("pk").annotate(author_count = Count("authors__nid")).filter(author_count__gt=1).values("title","author_count")    print(ret2)    return render(request, "index.html")

2.2.5F查询与Q查询

2.2.5.1F查询
from django.shortcuts import renderfrom django.db.models import F,Qfrom app1.models import *def index(request):    # 1.F查询,两个字段值作比较    ret1 = Book.objects.filter(price__gt=F("publish_id"))    print(ret1)    # 2.F查询与常数之间的加减乘除和取模    ret2 = Book.objects.filter(price__gt=F("publish_id")*100)    print(ret2)    # 3.支持批量更新    Book.objects.all().update(price=F("price")+30)    return render(request, "index.html")

2.2.5.2Q查询
from django.shortcuts import renderfrom django.db.models import F,Qfrom app1.models import *def index(request):    # 1.Q查询可以用于"或"查询,filter()方法是"and"查询    ret1 =Book.objects.filter(Q(authors__name="vita")|Q(authors__name="lili"))    print(ret1)    # 2.可以组合&和|以及~(取反)    # 作者名是vita,age!=23    ret2 = Book.objects.filter(Q(authors__name="vita")&~Q(authors__age=23))    print(ret2)    # 3.查询函数可以混合使用Q对象和关键字参数。关键字参数要放在最后面    ret3 = Book.objects.filter(Q(authors__age=23)|Q(publishDate__year=2012),title__startswith="S")    print(ret3)    return render(request, "index.html")

上述内容就是如何进行ORM多表操作,你们学到知识或技能了吗?如果还想学到更多技能或者丰富自己的知识储备,欢迎关注行业资讯频道。

查询 对象 字段 出版 方式 分组 作者 出版社 名称 数据 一对一 书籍 信息 下划线 模型 关联 关键 名字 价格 小写 数据库的安全要保护哪些东西 数据库安全各自的含义是什么 生产安全数据库录入 数据库的安全性及管理 数据库安全策略包含哪些 海淀数据库安全审计系统 建立农村房屋安全信息数据库 易用的数据库客户端支持安全管理 连接数据库失败ssl安全错误 数据库的锁怎样保障安全 中资互联网科技 青岛互联网科技公司 未来的互联网科技 碳银互联网科技有限公司 深圳期待互联网科技 卓越科技互联网 招聘 来此购互联网科技有限公司 互联网金融中的现代科技 宁夏科技产业互联网案例 彤创互联网科技有限公司 苏州五指互联网络科技有限 健康食品互联网创新科技园项目 互联网科技人工智能实验室 区块链结合互联网科技 每天都有哪些好的互联网科技 互联网科技职业技能培训学校 北京军民互联网科技公司 好易买互联网科技 亚光科技低轨卫星互联网 六子台科技互联网展会 远拓互联网科技 国外互联网科技网站 天扬科技互联网广告 恒生互联网科技指数跳水 华夏恒生互联网科技013171 明优互联网科技有限公司 沐思想互联网科技有限公司 南京一网一红互联网科技有限公司 保山互联网科技靠谱吗 杭州科技互联网公司有哪些
0