django ORM中的表关系
多对一:
为了方便理解,两个表之间使用ForeignKey连接时,使用ForeignKey的字段所在的表为从表,被ForeignKey连接的表为主表。
使用场景:书和出版社之间的关系,一本书只能由一个出版社出版,一个出版社却可以出版很多书
实现方式:一对多或者说多对一,在Django中是使用ForeignKey实现的,下面是例子:
class Publisher(models.Model):
"""出版社模型"""
id = models.AutoField(primary_key=True)
name = models.CharField(max_length=64,blank=True)
mobile = models.CharField(max_length=11,unique=True)
class Book(models.Model):
"""图书模型"""
name = models.CharField(max_length=64,blank=True)
content = models.TextField(blank=True)
pub_time = models.DateTimeField(auto_now_add=True)
publisher= models.ForeignKey(Publisher,on_delete=models.SET_NULL,
null=True,related_name='books')
详解:表中使用ForeignKey时,从表中会生成(该字段名+_id)的字段,该示例中在Book表中会生成publisher_id的字段,而在主表中则会默认的为我们添加一个(从表名小写+_set的属性),该属性是一个类似于objects的ReleatedManager对象,在该示例中默认应该是生成一个book_set的ReleatedManager对象,如果我们想要使用其他的名字代替(从表名小写+_set),我们需要在从表中使用ForeignKey的时候传递一个related_name参数,以后这个参数的值就会代替(从表名小写+_set),并且拥有其的所有属性和方法
多对一之添加数据:
1、从表中使用ForeignKey的字段传递主表的一行对象或者该字段名+_id传递主表中对应数据对象的id值:
publisher = Publisher(name='北京大学出版社',mobile='13395676110')
publisher.save()
book = Book(name='三国',content='东汉末年群雄争霸的故事')
book.publisher = publisher
book.save()
2、使用add函数,把从表中的一条或多条数据添加到主表中的一条数据中,此时会用的related_name的值:
publisher = Publisher(name='安徽出版社',mobile='16665678912',email='2399364196@qq.com')
publisher.save()
book = Book(name='梁祝',content='梁山伯与祝英台的爱情故事')
publisher.books.add(book,bulk=False) # 注意bulk参数的使用,如果book还没有在数据库中,当设置为FALSE,同时books的使用是因为我们设置了related_name='books'。
多对一之查询:
1、已知从表中的数据,查询主表中的数据,在此例中就是已知图书,查询这本书的出版社,其实这个时候就像操作查询类实例的属性一样操作就行了:
book = Book.objects.filter(pk=2).first()
print(book.publisher)
2、已知主表中的一条数据,查询出从表使用外键与之关联的所有数据,这时候我们就应该使用(从表名小写+_set)这个RelatedManager对象进行查询,注意这个对象可以使用filter,first等函数,当然这个对象在传递related_name参数简写,此例中使用这种简写方式:
publisher = Publisher.objects.filter(pk=2).first()
books = publisher.books.all() # 原生的应该是books = publisher.book_set.all()
for book in books:
print(book)
一对一:
同样,为了方便理解,我么设定使用OneToOneField字段所在的表为从表,OneToOneField字段连接的表为主表
使用场景:一般网站做用户信息统计的时候,通常会做两张表,一张存储常用信息,一张存储不常用的信息,这样做的目的也是为了查询的效率,此时这两张表就是一对一的关系
实现方式:在django中实现表与表之间的一对一关系使用的是OneToOneField,其实这个OneToOneField本质上讲就是ForeignKey,只不过在外键的基础上,使用该外键的字段增加了unique唯一约束:
class User(models.Model):
"""用户模型"""
name = models.CharField(max_length=64)
password = models.CharField(max_length=64)
age = models.PositiveSmallIntegerField()
class UserExtra(models.Model):
"""用户拓展模型"""
user = models.OneToOneField(User,on_delete=models.CASCADE,related_name='extra')
birthday = models.DateField()
address = models.CharField(max_length=128)
详解:在使用OneToOneField时,在从表中会生成一个该字段名+_id的字段,如user_id,而在主表中则会生成一个从表名小写的属性,用来关联从表中的相关数据,如userextra。当然在OneToOneField中你也可以传递一个related_name的参数,如'extra',这时候主表中数据就可以使用该参数的值去关联从表中的相关数据。
一对一之添加数据:
从表中使用OneToOneField的字段传递主表的一行对象或者该字段名+_id传递主表中对应数据对象的id值,其实操作就像是类对象设置保存属性一样:
user = User(name='李毛毛',password='limaomao',age=23)
user.save()
userextra = UserExtra(birthday=date,address='杭州市西湖区')
userextra.user = user
userextra.save()
一对一之查询:
1、已知从表中的一条数据,查询主表中相关联的数据,这时候就好像操作类实例去查询出它的一个属性一样:
userextra = UserExtra.objects.first()
print(userextra.user)
2、已知主表中的一条数据,查询从表中的相关数据,其实就是使用在OneToOneField创建时在主表中生成的以从表名小写命名的属性或者related_name中传递的值作为属性去查询出从表中相关数据:
user = User.objects.first()
userextra = user.extra
print(userextra)
多对多:
首先,为了方便理解,我们把使用ManyToManyField的字段所在的表称为从表,被连接的表称为主表。
应用场景:图书和作者之间关系,一本书可以有多个作者,一个作者可以写多本书
实现方式:在django中实现多对多是使用ManyToManyField,实质上是生成第三张中间表,在中间表中有两个外键分别连接从表和主表:
class Author(models.Model):
"""作者模型"""
name = models.CharField(max_length=32)
age = models.PositiveSmallIntegerField()
books = models.ManyToManyField('Book',related_name='authors')
class Book(models.Model):
"""图书模型"""
name = models.CharField(max_length=64,blank=True)
content = models.TextField(blank=True)
publisher = models.ForeignKey(Publisher,on_delete=models.SET_NULL,
null=True,related_name='books')
详解:当使用多对多的方式实现连表操作时,主表中将会自动被赋予一个从表名小写+_set的属性,这是一个ManyRelatedManager对象,这个属性名称当然也同样可以被简化成related_name所赋予的值,利用这个属性,我们可以在已知主表中的一条数据的情况下,查询出从表中所有与之关联的数据,同样这个属性同样也支持add函数,但是这个add函数与多对一之中的add函数不同,不能使用bulk参数,所以这里的添加操作都是已经在数据库中存在的数据,如果原先不存在,则必须先使用save函数保存到数据库。其实在从表中使用ManyToManyField的字段同样会变成一个属性,它同样也是一个ManyRelatedManager对象,因此多对多可以看做一个对称的过程
def many_to_many_view(request):
author = Author(name='徐大蒙',age=24)
author.save()
book = Book.objects.first()
book.authors.add(author)
return HttpResponse('success')
多对多之查询:
1、已知从表中的数据,查询主表中与之关联的所有数据:
author = Author.objects.first()
books = author.books.all() # 此时使用的是从表中使用ManyToManyField字段的字段名进行查询,这个字段也是一个ManyRelatedManager对象,也可以使用all(),filter()等函数
for book in books:
print(book)
2、已知主表中的数据查询从表中所有与之相关的数据:
book = Book.objects.get(pk=2)
authors = book.authors.all() # 未定义related_name的情况下使用book.author_set.all()
for author in authors:
print(author)
django ORM中的表关系的更多相关文章
- 优化Django ORM中的性能问题(含prefetch_related 和 select_related)
Django是个好工具,使用的很广泛. 在应用比较小的时候,会觉得它很快,但是随着应用复杂和壮大,就显得没那么高效了.当你了解所用的Web框架一些内部机制之后,才能写成比较高效的代码. 怎么查问题 W ...
- Django ORM 之 单表、多表查询
返回ORM目录 Django ORM Django ORM 之一 内容目录: 一.单表查询 二.多表查询 0.准备工作 一些说明: - 表myapp_person的名称是自动生成的,如果你要自定义表名 ...
- Python的Django框架中forms表单类的使用方法详解
用户表单是Web端的一项基本功能,大而全的Django框架中自然带有现成的基础form对象,本文就Python的Django框架中forms表单类的使用方法详解. Form表单的功能 自动生成HTML ...
- 数据库开发-Django ORM的单表查询
数据库开发-Django ORM的单表查询 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.查询集 1>.查询集相关概述 查询会返回结果的集,它是django.db.mod ...
- Django ORM 中的批量操作
Django ORM 中的批量操作 在Hibenate中,通过批量提交SQL操作,部分地实现了数据库的批量操作.但在Django的ORM中的批量操作却要完美得多,真是一个惊喜. 数据模型定义 首先,定 ...
- django ORM中的复选MultiSelectField的使用
下载和介绍: https://pypi.org/project/django-multiselectfield/ 在django ORM的使用中,经常会出现选择的情况,例如: class person ...
- Django中的表关系实现及操作
表关系的实现 预备知识 ORM的正向操作和反向操作: 1.正向操作:一个模型中定义了一个外键,通过该模型对该外键操作的操作叫做正向操作. 2.反向操作:被外键所关联的模型,通过该模型对外键所在模型 ...
- Django ORM中常用字段和参数
一些说明: 表myapp_person的名称是自动生成的,如果你要自定义表名,需要在model的Meta类中指定 db_table 参数,强烈建议使用小写表名,特别是使用MySQL作为后端数据库时. ...
- day 69 orm操作之表关系,多对多,多对一(wusir总结官网的API)
对象 关系 模型 wusir博客地址orm官网API总结 django官网orm-API orm概要: ORM 跨表查询 class Book(models.Model): title = mod ...
随机推荐
- aop 和castle 的一些 学习文章
https://www.cnblogs.com/zhaogaojian/p/8360363.html
- Java 文件切割工具类
Story: 发送MongoDB 管理软件到公司邮箱,工作使用. 1.由于公司邮箱限制附件大小,大文件无法发送,故做此程序用于切割大文件成多个小文件,然后逐个发送. 2.收到小文件之后,再重新组合成原 ...
- Yarn下分片和分块源代码分析
public class FileSplit extends InputSplit implements Writable { private Path file; private long star ...
- IIS配置MIME类型
有时候我们上传的视频,如果IIS上没有配置此格式是播放不了的.这个时候需要你在IIS上添加这个类型才能播放. MIME类型 ①打开你的IIS,点你的网站 ②双击 MIME类型 ③右键-->添加 ...
- EBS并发管理器启动失败,系统暂挂,在重置计数器之前修复管理程序
今天EBS安装补丁之后,因为停并发管理器的时候,因为关闭EBS应用时,并发管理器没有在前台停止,就直接停了应用服务,导致启动时,并发管理器直接起不来了,使用adcmctl.sh也没有办法启动. 进入系 ...
- C/C++获取本机名+本机IP+本机MAC
本机名.IP.MAC都是一些比较常用网络参数,怎么用C/C++获取呢? 研究了两三个小时... 需要说明的都在代码注释里 #include <stdio.h> #include <W ...
- Maven - 修改本地仓库位置
默认的本地仓库是在:当前的用户目录/.m2/repository 修改位置: 1. 打开maven的conf/settings.xml,找到如下图这一段: 2. 把<localRepositor ...
- 数据写入Excel
通过xlwt这个库,可以将数据写入Excel中,而且通过xlwt写excel格式可以控制 颜色.模式.编码.背景色 下面基本上是一个练习,熟悉如何操作xlwt库的 下面是代码,所有的内容,和介绍,基本 ...
- python中的字典内置方法小结
#!/usr/local/bin/python3 # -*- coding:utf-8 -*- #key-value #dict 无序,无下标,不需要下标,因为有key stu={ 'stu001': ...
- 编辑工具_vi
vi/vim平时经常会用到,但是一直没有时间系统的整理下,今天看到了一篇不错的介绍文章.引用下,就当做笔记了,但是不晓得该怎么填引用路径,如有侵权请告知,补上引用路径 01. vi 简介 1.1 学习 ...