Django-ORM之ForeignKey的使用-多对一关系
ForeignKey使用俩表示两张表多对一关系的外键,外键字段要定义在多属性的表中。
定义外键时,to的表可以直接写类名,但是需要注意类的定义顺序;也可以写字符串式的类名,这样就可以忽略class类的定义顺序;
class Book(models.Model):
title = models.CharField(max_length=32)
pid = models.ForeignKey('Publisher',on_delete=models.CASCADE) # 外键 on_delete属性 2.0 必填 ,1.0版本默认是models.CASCADE,建议是手动写上
【实例】
class Book(models.Model):
bid = models.AutoField(primary_key=True)
title = models.CharField(max_length=32)
pub = models.ForeignKey("Publisher", on_delete=models.CASCADE)
def __str__(self):
return f"{self.bid}{self.title}{self.pub}"
创建完成后会发生如图这种情况,pub自动变成了pub_id,无需惊讶,这就是它应有的样子~

那么pub与pub_id之间有什么关系呢?听经过查看pub的type可以得出结论,pub得到的是一个对象,包含pub_id在内的外键对应的对象,在django中创建外键时,默认是以目标的主键作为对应项,以下的各个操作就会利用这一点。
在本例中外键中
pub_id == pub.pid
查询
all_books = models.Book.objects.all()
print(all_books)
for book in all_books:
print(book)
print(book.pk)
print(book.title)
print(book.pub,type(book.pub)) # 所关联的对象
print(book.pub_id,type(book.pub_id)) # 所关联的对象的pk
print('*' * 32)
新增
# 方式一
models.Book.objects.create(title=title,pub=models.Publisher.objects.get(pk=pub_id))
# 方式二
models.Book.objects.create(title=title, pub_id=pub_id)
删除
pk = request.GET.get('pk')
models.Book.objects.filter(pk=pk).delete()
编辑
book_obj.title = title
# 修改外键列
# 方式一:
book_obj.pub_id = pub_id
# 方式二:
book_obj.pub = models.Publisher.objects.get(pk=pub_id)
book_obj.save()
外键的操作
【新建测试表结构】
from django.db import models
# Create your models here.
class Publisher(models.Model):
name = models.CharField(max_length=32)
city = models.CharField(max_length=32)
def __str__(self):
return "<Publisher object: {} {}>".format(self.id, self.name)
class Author(models.Model):
name = models.CharField(max_length=32)
age = models.IntegerField()
phone = models.CharField(max_length=11)
def __str__(self):
return "<Author object: {} {}>".format(self.id, self.name)
class Book(models.Model):
title = models.CharField(max_length=32)
publish_date = models.DateField(auto_now_add=True)
price = models.DecimalField(max_digits=5, decimal_places=2)
memo = models.TextField(null=True)
# 创建外键,关联publish
publisher = models.ForeignKey(to="Publisher",null=True, on_delete=models.CASCADE)
# 创建多对多关联author
author = models.ManyToManyField(to="Author")
def __str__(self):
return "<Book object: {} {} {} {}>".format(self.id, self.title,self.price,self.author)
跨表对象查找正向
所谓正向查找是指从建立外键的表查询目标表的查找,兄目标表查询建立外键的表就是反向查询。
book_obj = models.Book.objects.first()
print(book_obj) # 输出book对象
print(book_obj.publisher) # book对象对应的外键对象
print(book_obj.publisher.name) # 外键对象的name属性
跨表对象查找反向
pub_obj = models.Publisher.objects.get(pk=1)
print(pub_obj) # 出版社对象
print(pub_obj.name) # 出版社名称
print(pub_obj.book_set) # 关系管理对象,与该出版社相关联的图书的关系,默认的书写方式:类名小写_set
print(pub_obj.book_set.all()) # 所关联的所有的对象
添加relate_name属性
定义反向查询时的名字,例如将Book表的publisher属性添加related_name属性,会抵消默认情况的类名小写_set:
# 添加属性
publisher = models.ForeignKey(to="Publisher",null=True, on_delete=models.CASCADE,related_name='books')
# 未添加属性时,反向查询
pub_obj = models.Publisher.objects.get(pk=1)
print(pub_obj.book_set)
print(pub_obj.book_set.all())
# 添加属性后的反向查询
pub_obj = models.Publisher.objects.get(pk=1)
print(pub_obj.books)
print(pub_obj.books.all())
跨表字段查找正向
# 查询'叽叽喳喳出版社'出版的书
ret = models.Book.objects.filter(publisher__name='叽叽喳喳出版社')
print(ret.all())
跨表字段查找反向
# 查找出版《叽叽喳喳》的出版社
ret = models.Publisher.objects.filter(book__title='叽叽喳喳')
print(ret.values())
添加related_name属性
# 添加属性
publisher = models.ForeignKey(to="Publisher",null=True, on_delete=models.CASCADE,related_name='books')
# 反向查询时
ret = models.Publisher.objects.filter(books__title='叽叽喳喳')
print(ret)
添加related_query_name属性
在字段查找时related_query_name的优先级高于related_name,但是在对象查找时,related_query_name无效
publisher = models.ForeignKey(to="Publisher",null=True, on_delete=models.CASCADE,related_name='books',related_query_name='books1')
# 反向查询时
ret = models.Publisher.objects.filter(books1__title='叽叽喳喳')
print(ret)
关系管理对象的方法
反向查询时才能取到关系管理对象
# all
pub_obj = models.Publisher.objects.get(pk=1)
print(pub_obj.book_set.all())
# set 设置对象
pub_obj.book_set.set(models.Book.objects.filter(pk__in=[3,4]))
# add 添加对象
pub_obj.book_set.add(*models.Book.objects.filter(pk__in=[1,2]))
# remove 移除外键,前提是外键字段可以为空
pub_obj.book_set.remove(*models.Book.objects.filter(pk__in=[1,2]))
# clear 清空,前提是外键字段可以为空
pub_obj.book_set.clear(*models.Book.objects.filter(pk__in=[1,2]))
# create
pub_obj.book_set.createtitle='叽叽喳喳的世界',publisher_id=2,price=99.9)
Django-ORM之ForeignKey的使用-多对一关系的更多相关文章
- django数据库操作-增删改查-多对多关系以及一对多(外键)关系
一.一对多(外键) 例子:一个作者对应多本书,一本书只有一个作者 model代码: class Person(models.Model); name = models.CharField('作者姓名' ...
- 转: django数据库操作-增删改查-多对多关系以及一对多(外键)关系
原文链接:http://blog.csdn.net/u010271717/article/details/22044415 一.一对多(外键) 例子:一个作者对应多本书,一本书只有一个作者 model ...
- Django框架之第六篇(模型层)--单表查询和必知必会13条、单表查询之双下划线、Django ORM常用字段和参数、关系字段
单表查询 补充一个知识点:在models.py建表是 create_time = models.DateField() 关键字参数: 1.auto_now:每次操作数据,都会自动刷新当前操作的时间 2 ...
- Django ORM 多表操作
目录 Django ORM 多表操作 表模型 表关系 创建模型 逆向到表模型 插入数据 ORM 添加数据(添加外键) 一对多(外键 ForeignKey) 一对一 (OneToOneFeild) 多对 ...
- django -- 多对多关系的实现
在django中表和表之间的多对多关系有两种实现方案: 方案一:直接使用django自动实现的多对多关系. 方案二:自己写连接表.然而告诉django在实现多对多关系时要使用的连接表. 一.方案一: ...
- Django ORM、一对一、一对多、多对多、详解
上篇博客也提到这些知识点,可能大家还是不太清楚,这篇博客为大家详细讲解ORM中的几个知识点 1.1首先我们先看一个小案例: #_*_coding:utf-8_*_ from django.db imp ...
- Django --ORM常用的字段和参数 多对多创建形式
1 ORM字段 AutoField int自增列,必须填入参数 primary_key=True.当model中如果没有自增列,则自动会创建一个列名为id的列. IntegerField 一个整数类型 ...
- django ORM模型表的一对多、多对多关系、万能双下划线查询
一.外键使用 在 MySQL 中,如果使用InnoDB引擎,则支持外键约束.(另一种常用的MyIsam引擎不支持外键) 定义外键的语法为fieldname=models.ForeignKey(to_c ...
- 数据库开发-Django ORM的多对多查询
数据库开发-Django ORM的多对多查询 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.联合主键问题 CREATE TABLE `employees` ( `emp_no` ...
随机推荐
- Python模拟百度自动输入搜索功能
# 访问百度,模拟自动输入搜索 # 代码中引入selenium版本为:3.4.3 # 通过Chrom浏览器访问发起请求 # Chrom版本:59 ,chromdriver:2.3 # 需要对应版本的C ...
- BZOJ 4127: Abs (树链剖分 线段树求区间绝对值之和 带区间加法)
题意 给定一棵树,设计数据结构支持以下操作 1 u v d 表示将路径 (u,v) 加d(d>=0) 2 u v 表示询问路径 (u,v) 上点权绝对值的和 分析 绝对值之和不好处理,那么我们开 ...
- 题解 【POJ1014】 Dividing
题目意思 有六种不同的石子,权值为\(1\)~\(6\),给出六种石子的数量,求能否将石子分成权值相等的两份. 解析 这题可以直接用多重背包写, 因为仔细想想, 能够平均分成两份, 也就是能将一部分石 ...
- 清除Tomcat缓存
删除tomcat目录下的缓存文件分别位于: tomcat/work tomcat/temp ...
- Flutter 父子组件传值
Flutter 父子组件传值 一父传子: 父中: void onButtonChange(val1,val2,val3){ print('============================子向父 ...
- hdu 5533 正n边形判断 精度处理
Dancing Stars on Me Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 262144/262144 K (Java/Ot ...
- bk复面-一场被问蒙蔽了的面试
1.自我介绍 ---自我介绍从个人生活上.兴趣爱好上去介绍,比如我自己,平时喜欢听听音乐.看看鸡汤类的书,比如爱下厨,喜欢根据一些网上的教程去尝试做一份自己满意的晚餐,简历上已经写得工 ...
- postgresql-基础-1
概述 层状关系 网状关系 关系型数据库 关系型数据库 元祖:代表一行 属性:代表一列 主码:唯一确定一个元组的属性组,即主键 域:属性的取值范围 分量:元组中的一个属性值,即某一行 ...
- [CSP-S模拟测试]:C(三分+贪心)
题目传送门(内部题46) 输入格式 第一行$3$个整数$n,m,t$.第二行$n$个整数,表示$P_i$.接下来$m$行每行两个整数,表示$L_i,R_i$. 输出格式 一行一个整数表示答案. 样例 ...
- [CSP-S模拟测试]:任务分配(最短路+贪心+DP)
题目传送门(内部题149) 输入格式 每个测试点第一行为四个正整数$n,b,s,m$,含义如题目所述. 接下来$m$行,每行三个非负整数$u,v,l$,表示从点$u$到点$v$有一条权值为$l$的有向 ...