如何进行ORM多表操作

发布时间:2021-11-25 18:49:05 作者:柒染
来源:亿速云 阅读:193

本篇文章为大家展示了如何进行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")

如何进行ORM多表操作
如何进行ORM多表操作
如何进行ORM多表操作
如何进行ORM多表操作

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插入数据

如何进行ORM多表操作

2.1.1一对多插入数据

from django.shortcuts import render
from 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)

如何进行ORM多表操作

2.1.2多对多插入数据

from django.shortcuts import render
from 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")

如何进行ORM多表操作

2.1.3多对多的关键点

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

如何进行ORM多表操作

2.1.4多对多解除绑定

book_obj.authors.remove()      # 将某个特定的对象从被关联对象集合中去除。    ======   book_obj.authors.remove(*[])
book_obj.authors.clear()       #清空被关联对象集合
book_obj.authors.set()         #先清空再设置
from django.shortcuts import render
from 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")

如何进行ORM多表操作

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准备数据

如何进行ORM多表操作
如何进行ORM多表操作
如何进行ORM多表操作

如何进行ORM多表操作
如何进行ORM多表操作

2.2.2.2基于对象查询--一对多查询
from django.shortcuts import render
from 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)  # <QuerySet [<Book: Book object (7)>, <Book: Book object (9)>, <Book: Book object (10)>, <Book: Book object (11)>]>
    # SQL语句:

    return render(request, "index.html")

如何进行ORM多表操作

2.2.2.3基于对象查询--多对多查询
from django.shortcuts import render
from app1.models import *
def index(request):
    # 多对多正向查询:查询Sanguo这本书的所有作者名字
    # 书和作者是多对多关系,返回值是queryset集合。
    # <QuerySet [<Author: Author object (1)>, <Author: Author object (2)>]>
    author_list = Book.objects.filter(title="SanGuo").first().authors.all()
    print(author_list)

    # 多对多反向查询:查询vita出版过的所有书籍名称
    # 书和作者是多对多关系,返回值是queryset集合。
    # <QuerySet [<Book: Book object (7)>, <Book: Book object (8)>, <Book: Book object (9)>, <Book: Book object (10)>, <Book: Book object (11)>]>
    book_list = Author.objects.filter(name="vita").first().book_set.all()
    print(book_list)
    return render(request, "index.html")

如何进行ORM多表操作

2.2.2.4基于对象查询--一对一查询
from django.shortcuts import render
from 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")

如何进行ORM多表操作

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

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

    # 一对多查询:查询 AA_publish出版社出版的书籍名称
    # 返回值是queryset对象
    # 方式一正向查询:
    ret3 = Publish.objects.filter(name="AA_publish").values("book__title")
    print(ret3)  # <QuerySet [{'book__title': 'SanGuo'}, {'book__title': 'HongLou'}, {'book__title': 'XiYou'}, {'book__title': 'XiaoWangZi'}]>
    # 方式二反向查询:
    ret4 = Book.objects.filter(publish__name="AA_publish").values("title")
    print(ret4)  # <QuerySet [{'title': 'SanGuo'}, {'title': 'HongLou'}, {'title': 'XiYou'}, {'title': 'XiaoWangZi'}]>
    return render(request, "index.html")

如何进行ORM多表操作

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

    return render(request, "index.html")

如何进行ORM多表操作

2.2.3.3基于双下划线的跨表查询--一对一查询
from django.shortcuts import render
from app1.models import *
def index(request):
    # 一对一查询:查询vita的手机号
    # 返回值queryset对象
    # 方式一:正向查询
    ret1 = Author.objects.filter(name="vita").values("authorDetail__telephone")
    print(ret1)  # <QuerySet [{'authorDetail__telephone': 112233}]>

    # 方式二:反向查询
    ret2 = AuthorDetail.objects.filter(author__name="vita").values("telephone")
    print(ret2)  # <QuerySet [{'telephone': 112233}]>
    return render(request, "index.html")

如何进行ORM多表操作

2.2.3.4基于双下划线的跨多表查询
from django.shortcuts import render
from 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")

如何进行ORM多表操作

2.2.4聚合与分组查询

2.2.4.1aggregate聚合查询
返回值是字典
from django.shortcuts import render
from django.db.models import Avg,Max,Min,Count
from 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")

如何进行ORM多表操作

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 render
from django.db.models import Avg,Max,Min,Count
from 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)  # <QuerySet [{'price': Decimal('100.00'), 'book_count': 2}, {'price': Decimal('120.00'), 'book_count': 3}]>
    return render(request, "index.html")

如何进行ORM多表操作

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

如何进行ORM多表操作

from django.shortcuts import render
from django.db.models import Avg,Max,Min,Count
from 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")

如何进行ORM多表操作

from django.shortcuts import render
from django.db.models import Avg,Max,Min,Count
from 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")

如何进行ORM多表操作

from django.shortcuts import render
from django.db.models import Avg,Max,Min,Count
from 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")

如何进行ORM多表操作

2.2.5F查询与Q查询

2.2.5.1F查询
from django.shortcuts import render
from django.db.models import F,Q
from 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")

如何进行ORM多表操作

2.2.5.2Q查询
from django.shortcuts import render
from django.db.models import F,Q
from 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多表操作

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

推荐阅读:
  1. Django ORM 操作例
  2. 如何进行mysql多表查询

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

orm

上一篇:如何理解MultiScanner模块化文件扫描与分析框架

下一篇:C#如何实现基于Socket套接字的网络通信封装

相关阅读

您好,登录后才能下订单哦!

密码登录
登录注册
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》