六、Django ORM关联模型
本章节将介绍ORM中的关联模型,以下测试基于book管理
一、创建关联模型
创建app01并注册
编辑全局settings.py文件,如下:
INSTALLED_APPS = ['django.contrib.admin','django.contrib.auth','django.contrib.contenttypes','django.contrib.sessions','django.contrib.messages','django.contrib.staticfiles','app01.apps.App01Config', ###添加app01的配置
]
配置数据库连接
编辑全局settings.py文件,如下:
DATABASES = {'default': {'ENGINE': 'django.db.backends.mysql','NAME': 'Django','USER': 'root','PASSWORD': '123456','HOST': 'locahost','PORT': '3306',}
}
创建关联模型
编辑app01下的models.py文件,如下:
from django.db import modelsclass Book(models.Model):title = models.CharField(max_length=32)price = models.DecimalField(max_digits=8, decimal_places=2) # 999999.99,浮点型8位数,小数点2位publishDate = models.DateField()# 一对多的关联属性,创建关联字段publish = models.ForeignKey("Publish", on_delete=models.CASCADE) ###表中会添加一个publish_id字段,并设置级联删除# 多对多的关联属性,创建关系表authors = models.ManyToManyField("Author", db_table="book2author") # 多对多的时候,一般通过第三方表来实现,如果不命名的话,会自动创建一个book_authors的表class Publish(models.Model):name = models.CharField(max_length=32)addr = models.CharField(max_length=32)email = models.CharField(max_length=32)class Author(models.Model):name = models.CharField(max_length=32)age = models.SmallIntegerField()###设置一对一的关联属性ad = models.OneToOneField("AuthorDetail", on_delete=models.CASCADE) ##添加ForeignKey时需设置级联删除。class AuthorDetail(models.Model):tel = models.IntegerField()addr = models.CharField(max_length=32)
具体解释如下:
- 一对多
在一对多的关系中,需要使用models.ForeignKey在表示“多”的模型中定义一个外键字段,定义时需要指定表示“一”的模型类名。models.ForeignKey常用参数:
- to:该属性的第一个参数,表示外键指向的模型类的类名
- on_delete:表示外键指向的数据不存在时,本条数据该如何处理。- CASCADE:级联操作,如果外键对应的在另一张表中的数据被删除了,那么本条数据也会被跟着删除。- PROTECT:外键数据受保护,即只要本条数据还存在,则外键对应的在另一张表中的数据是无法被删除的。- SET_NULL:删除时设置为空,如果外键对应的在另一张表中的数据被删除了,那么本条数据中的这个外键值就设置为空。- SET_DEFUALT:设置为默认值,如果外键对应的在另一张表中的数据被删除了,那么本条数据中的这个外键值就设置为指定的默认值,但前提是此字段有指定的默认值。- SET(obj/func):设置默认值,如果外键对应的在另一张表中的数据被删除了,那么本条数据中的这个外键值就设置为指定的值obj或者指定函数或方法func的返回值。- DO_NOTHING:不做任何操作,一切只看数据库本身的约束。
- related_name: 一般用于反向查询,表示“多”的模型中定义外键后,Django会在表示“一”的模型中自动生成一个表示“多”的模型类名_set属性,如果不想使用这种默认的命名方式,就可以使用此参数指定自己需要的名称了。 - db_constraint:默认为True,指有外键约束,如果只想设置关联数据,取消外键约束,设置为Flase即可。
参考related.py文件,如下定义的ForeignKey方法:
def __init__(self, to, related_name=None, related_query_name=None,limit_choices_to=None, symmetrical=None, through=None,through_fields=None, db_constraint=True, db_table=None,swappable=True, **kwargs):try:to._metaexcept AttributeError:assert isinstance(to, str), ("%s(%r) is invalid. First parameter to ManyToManyField must be ""either a model, a model name, or the string %r" %(self.__class__.__name__, to, RECURSIVE_RELATIONSHIP_CONSTANT))
- 多对多
使用models.ManyToManyField指定即可(定义多对多关系时,Django会在数据库中自动生成一个关联两张表的中间表,但是在Django中不用我们自己去定义),同样的,也会在另一个模型中自动生成一个形如类名_set的属性。
- 一对一
使用models.OneToOneField指定即可,定义方法和参数使用与models.ForeignKey类似(因为models.OneToOneField就是通过models.ForeignKey来实现的,只不过是添加了一个“唯一”的约束),不同之处在于,在另一个外键对应的模型中自动生成的属性为类名的小写形式,当然,你不想用默认生成的属性,也可以通过related_name参数来指定。
添加数据
在models.py文件中添加如下内容:
AuthorDetail.objects.create(tel=122121212,addr="北京")
AuthorDetail.objects.create(tel=212121212,addr="南京")
AuthorDetail.objects.create(tel=313131313,addr="上海")
Publish.objects.create(name="北京出版社",addr="昌平",email="122122")
Publish.objects.create(name="南京出版社",addr="中山路",email="212122")
Publish.objects.create(name="上海出版社",addr="浦东",email="313313133")
执行数据库迁移
python manage.py makemigrations ###生成迁移文件
python manage.py migrate ###同步数据库
二、关联模型操作
一对多增删改查
- 创建路由
编辑全局配置文件urls.py文件,如下:
from django.contrib import admin
from django.urls import path
from app01 import views as app1
urlpatterns = [path('admin/', admin.site.urls),path('index',app1.addbook),]
- 增加
from django.shortcuts import render,HttpResponse,redirect
from app01.models import Book,Publish,Author,AuthorDetail
def addbook(request):##向book表中添加一条数据##获取出版社名称publish = Publish.objects.get(name="北京出版社")##方法一book = Book.objects.create(title="西游记",price=100,publishDate="2022-12-2",publish=publish)###方法二book = Book.objects.create(title="红楼梦", price=200, publishDate="2021-11-2", publish_id=5)book = Book.objects.create(title="水浒传", price=180, publishDate="2020-10-2", publish_id=6)###打印相关内容print(book1.title) ###book对象中title已经复制到内存中print(book1.publish) ###打印结果为一个对象print(book1.publish.name) ###Django关联模型中会利用publish_id获得publish(get方式)的模型类对象print(book1.publish_id) ##得到的就是当前book记录的publish_id,return HttpResponse("成功")
运行django程序,界面登录,查看数据库添加成功
- 删除
from django.shortcuts import render,HttpResponse,redirect
from app01.models import Book,Publish,Author,AuthorDetail
def addbook(request):##将book表中删除一条数据Book.objects.filter(title="西游记").delete() ##直接删除即可return HttpResponse("成功")
- 更新
from django.shortcuts import render,HttpResponse,redirect
from app01.models import Book,Publish,Author,AuthorDetail
def addbook(request):##更新表中的数据Book.objects.filter(title="红楼梦").update(name="三国演义") ##直接更新return HttpResponse("成功")
- 查看
from django.shortcuts import render,HttpResponse,redirect
from app01.models import Book,Publish,Author,AuthorDetail
def addbook(request):##查看表中的数据book = Book.objects.filter(name="三国演义") ##和之前讲的一样,就不再次赘述print(book)return HttpResponse("成功")
多对多增删改查
- 增加
from django.shortcuts import render,HttpResponse,redirect
from app01.models import Book,Publish,Author,AuthorDetail
def addbook(request):##为book书籍添加作者##方法一##获取book信息book = Book.objects.get(title="水浒传")author1 = Author.objects.get("小华")author2 = Author.objects.get(name="小明")book.authors.add(author1, author2)##方法二book = Book.objects.get(title="水浒传")book.authors.add(1, 2) ###可以直接跟authorID##方法三book = Book.objects.get(title="水浒传")author_list = [1,2] ###将作者定义为列表book.authors.add(*author_list) ##将列表中的数据传进去return HttpResponse("成功")
运行django程序,查看第三张关联表,如下:
- 删除
from django.shortcuts import render,HttpResponse,redirect
from app01.models import Book,Publish,Author,AuthorDetail
def addbook(request):###删除书的作者book = Book.objects.get(title="水浒传")book.authors.remove(2) ###删除指定作者对象####book.authors.clear() ###删除该book下关联的所有作者对象return HttpResponse("成功")
- 修改
from django.shortcuts import render,HttpResponse,redirect
from app01.models import Book,Publish,Author,AuthorDetail
def addbook(request):###更新书的作者book = Book.objects.get(title="水浒传")book.authors.set([6,]) ###先clear删除后add添加return HttpResponse("成功")
运行django程序,查看结果
也可以看到sql的运行过程,是先根据bookID
从app01_author
表中查出来该book对应的author的信息,在进行delete
删除,之后进行insert
添加,如下:
- 查看
from django.shortcuts import render,HttpResponse,redirect
from app01.models import Book,Publish,Author,AuthorDetail
def addbook(request):###查询书的作者book = Book.objects.get(title="水浒传")author_list = book.authors.all().values("name","age")print(author_list)return HttpResponse("成功")
运行django程序,结果如下:
一对一增删改查
此处不多讲,只演示如何添加数据
from django.shortcuts import render,HttpResponse,redirect
from app01.models import Book,Publish,Author,AuthorDetail
def addbook(request):##添加一条作者信息author = Author.objects.create(name="小华",age=40,ad_id=3)return HttpResponse("成功")
反向查询
前面介绍的都是基于book查看author,下面来介绍如何基于author查看book
上面说到创建多对多关联模型的时候,添加了related_name="books"参数,后面的名字可以随意定义
具体步骤如下:
from django.shortcuts import render,HttpResponse,redirect
from app01.models import Book,Publish,Author,AuthorDetail
def addbook(request):###反向查询###通过作者查出对应的书籍authtor = Author.objects.get(pk=6) ###获取author的信息print(authtor.books.all().values("title")) ###通过author调用books对象获取book信息return HttpResponse("成功")
大致原理如下:
1: 通过定义的related_name得知是和哪张表是多对多的关系
2: 然后通过第三张关联表的authorID获取所有的book信息
3:通过获取的book对象来查找具体的哪个属性的信息
运行django程序,结果如下:
查看数据库中的数据,结果一致,如下:
六、Django ORM关联模型相关推荐
- django orm关联查询_django中orm的多表查询
一.创建模型 下面我们通过图书管理系统,来设计出每张表之间的对应关系. 通过上图关系,来定义一下我们的模型类. from django.db import models class Book(mode ...
- django orm关联查询_Django ORM 聚合查询和分组查询实现详解
models.py: from django.db import models # 出版社 class Publisher(models.Model): id = models.AutoField(p ...
- django ORM中的RelatedManager(关联管理器)
关联管理器应用在 一对多的表 或者 多对多的表 多对多表中的用法: 在多对多的表中 正向查询 #基于对象的查询 #正查 # author_obj = Author.objects.get(id=1) ...
- Django ORM – 多表实例:Django模型Model的定义+模型间关系
Django 对各种数据库提供了很好的支持,包括:PostgreSQL.MySQL.SQLite.Oracle. Django 为这些数据库提供了统一的调用API. 我们可以根据自己业务需求选择不同的 ...
- django orm原理_django 动态创建一个模型的多个table name, 并通过 Django ORM 操作
动态创建table, 并通过 Django ORM 操作. 动态的创建表 动态的创建模型其实就是在运行时生成 Model 类, 这个可以通过函数实现, 通过传参(今天的日期, 如: 20181211) ...
- Django - ORM操作
Django - ORM操作 一. 必知必会13条 单表查询之神奇的双下划线 二. ForeignKey操作 正向查找 反向操作 三. ManyToManyField 四. 聚合查询和分组查询 聚合 ...
- Django框架的模型层之多表操作
目录 一 创建模型 二 表记录的增删改 一对多 多对多 三.基于对象的跨表查询 一对一查询(Author 与 AuthorDetail) 一对多查询(publish与book) 多对多查询 (Auth ...
- django orm级联_Django数据表关联关系映射(一对一、一对多、多对多)
我们知道涉及到数据表之间的对应关系就会想到一对一.一对多.多对多,在学习 MySQL 数据库时表关系设计是需要重点掌握的知识.Django 中定义了三种关系类型的字段用来描述数据库表的关联关系:一对多 ...
- django ORM相关的那些操作汇总
必知必会13条 <1> all(): 查询所有结果<2> filter(**kwargs): 它包含了与所给筛选条件相匹配的对象<3> get(**kwargs): ...
最新文章
- OpenSCAD 建模:矿泉水瓶盖
- 文件资源管理右键卡死无响应
- 射雕三部曲的优美片段
- Python 字符串 String 内建函数大全(1)
- spring elasticsearch 按条件删除_SpringBoot2 高级案例(08):整合 ElasticSearch框架,实现高性能搜索引擎...
- mysql 游标的简单_mysql 简单游标
- 【JAVA】Java中goto语句的简介与使用(java 如何跳出内嵌多层循环的方法)
- Matlab标准语音库 Timit Database
- “C语言” 读书札记(五)之[让我们一起学习汇编吧!(段)]
- insmod module 失败(skyeye + armlinux)
- 百度远场语音识别套件-开箱评测
- 【BZOJ 3681】Arietta
- Winform 调整SplitContainer中Panel的大小
- Ubuntu磁盘分区和挂载
- MongoDB分片机制
- Java13新增特性
- 上传资料总是显示服务器异常,云盘上传总是服务器异常
- 【学习周报】深度学习笔记第二周
- 高仿Telegram IM Chat 聊天软件 即时通讯 在线聊天加社群 纯静态UI架构介绍
- 并行算法设计与性能优化 刘文志 第2章 现代处理器特性
热门文章
- 计算机视觉的最终表现!三维重建技术
- 西方哲学智慧2018网课考题(本人亲测,已满分)
- PYTHON第二次实验
- 小红书api_【实习精选】oppo、小红书等名企实习汇总(96)
- BZOJ4765 普通计算姬
- 《Android游戏编程入门经典》——1.1节Android 4简介
- 计算机专业论文 方向,计算机专业本科生方向论文题目 计算机专业本科生论文题目怎样取...
- Android中InCallUI显示太慢问题分析
- YSO小游戏·VB6版代码
- 【我的DOT语言学习之旅】 学习DOT语言并使用Graphviz软件来打开.dot文件