表之间的关系
- 一对一
xx=models.OneToOneField(to='要关联的表名',to_field='要关联表名的字段',on_delete=models.CASCADE)
# on_delete 删除时的一些级联效果,to_field可以不用写,默认是关联到另一张表的主键,on_field在1.x版本的Django中不用写,默认是级联删除的,2.x的版本中必须要写
- 一对多
xx=models.foreignKey(to='要关联的表名',to_field='要关联表名的字段',on_delete=models.CASCADE)
- 多对多
xx = models.ManyToManyField(to='另外一个表名') #这是自动创建的第三表
建表准备
- 建立四张表: 作者表 -- 作者信息表 -- 出版社表 -- 书籍表
- 表之间的对应关系如下
- 一个作者应该对应一个相应的作者信息,所以作者表与作者信息表的关系为一对一 : oneToOnefield
- 一个出版社可以出版很多书,一本书也可以有多个出版社出版,为多对多,但是在这里将此设置为一个出版社出很对书,一对多的关系: foreignkey
- 作者和书籍的关系为多对多: ManyToManyField

# 作者表
class Author(models.Model):
name=models.CharField( max_length=32)
age=models.IntegerField()
#authorDetail=models.OneToOneField(to="AuthorDetail",to_field="nid",on_delete=models.CASCADE)
authorDetail=models.OneToOneField(to='AuthorDetail') #一对一到AuthorDetail表 生成为表字段之后,会自动变为authorDetail_id这样的一个名称
def __str__(self):
return self.name
# 作者详细信息表
class AuthorDetail(models.Model):
birthday=models.DateField()
telephone=models.CharField(max_length=32)
addr=models.CharField( max_length=64)
def __str__(self):
return self.addr
# 出版社表和书籍表 是 一对多的关系
class Publish(models.Model):
name=models.CharField( max_length=32)
city=models.CharField( max_length=32)
email=models.EmailField()
def __str__(self):
return self.name
# 书籍表
class Book(models.Model):
nid = models.AutoField(primary_key=True)
title = models.CharField( max_length=32)
publishDate=models.DateField()
price=models.DecimalField(max_digits=5,decimal_places=2) # 整数位5位,小数位2位
publishs=models.ForeignKey(to="Publish")
authors=models.ManyToManyField(to='Author',) # 注意不管是一对多还是多对多,写to这个参数的时候,最后后面的值是个字符串,不然你就需要将你要关联的那个表放到这个表的上面
def __str__(self):
return self.title
View Code
增加数据
- 一对一增加(先给作者详细信息表中增加数据,再增加作者表的数据)
new_author_detail = models.AuthorDetail.objects.create(
birthday='1979-08-08',
telephone='138383838',
addr='北京',
)
obj = models.AuthorDetail.objects.filter(addr='山西').first()
#方式1
models.Author.objects.create(
name='张三',
age='40',
authorDetail=new_author_detail,
)
# 方式2 常用
models.Author.objects.create(
name='张三',
age='40',
authorDetail_id=obj.id,
)
- 一对多增加
# 方式1
models.Book.objects.create(
title = '追风筝的人',
publishDate='2019-07-22',
price=25,
publishs=models.Publish.objects.get(id=1),
)
# 方式2 常用
obj = models.Publish.objects.get(id=1)
models.Book.objects.create(
title='追风筝的人',
publishDate='2019-07-21',
price=25,
publishs_id=obj.id
)
- 多对多增加
# 方式1 常用
book_obj = models.Book.objects.get(id=1) # 拿到book的id
book_obj.authors.add(*[1,2]) # 插入作者的id 打散的形式插入
# 方式2
author1 = models.Author.objects.get(id=1)
author2 = models.Author.objects.get(id=3)
book_obj = models.Book.objects.get(nid=5)
book_obj.authors.add(*[author1,author2])
删除数据
一对一和一对多的删除和单表删除是一样的
# 一对一 表一外键关联到表二,表一删除,不影响表2,表2删除会影响表1
# 作者表外键关联作者详细信息表
models.AuthorDetail.objects.get(id=2).delete() # 作者表会受影响
models.Author.objects.get(id=3).delete() # 作者详细信息表不会影响
# 一对多
# 书籍表外键关联出版社表
models.Publish.objects.get(id=1).delete() # 书籍表会影响
models.Book.objects.get(id=1).delete() # 出版社表不会影响
# 多对多关系删除
book_obj = models.Book.objects.get(nid=6)
book_obj.authors.remove(6) # 删除书id为6和作者id为6的一行数据
book_obj.authors.remove(*[5,6])
book_obj.authors.clear() # 清空表中所有数据
book_obj.authors.set('1') #删除然后更新,后面写字符串
book_obj.authors.set(['5','6'])
更新数据
# 一对一
models.Author.objects.filter(id=5).update(
name='张三',
age=16,
authorDetail=models.AuthorDetail.objects.get(id=5),
authorDetail_id=4,
)
#一对多
models.Book.objects.filter(pk=4).update( # pk=4等价于id=4
title='白夜行',
publishs=models.Publish.objects.get(id=3),
publishs_id=3,
)
#一对多
models.Publish.objects.filter(pk=2).update(
id=4, # 没有级联更新,报错!!
)
基于对象的跨表查询
- 类似于子查询
- 正向查询和反向查询: 关系属性(字段)写在哪个类(表)里面,从当前类(表)的数据去查询它关联类(表)的数据叫做正向查询,反之叫做反向查询

############## 一对一
查询Alex的电话号码(正向查询)
obj = models.Author.objects.get(name='alex')
print(obj.authorDetail.telephone)
反向查询: 查询333这个号码是谁的
#obj = models.AuthorDetail.objects.filter(telephone='333').first().author.name
obj = models.AuthorDetail.objects.get(telephone='333').author.name
print(obj)
''' 正向查询: Authorobj.authorDetail,对象.关联属性名称
Author -----------------------------------> AuthorDetail
<-----------------------------------
反向查询: AuthorDetailobj.author ,对象.小写类名
'''
######### 一对多
查询追风筝的人是哪个出版社出版的(正向查询)
obj = models.Book.objects.get(title='追风筝的人')
print(obj.publishs.name,obj.publishs.city)
查看新华出版社出了什么书(反向查询)
obj = models.Publish.objects.get(name='人民出版社')
for i in obj.book_set.all(): # 循环拿到具体的值
print(i)
''' 正向查询 book_obj.publishs 对象.属性
Book ---------------------------------------------> Publish
<----------------------------------------------
反向查询 publish_obj.book_set.all() 对象.表名小写_set
'''
########## 多对多
查看狼道这本书是谁写的(正向查询)
obj = models.Book.objects.get(title='狼道')
for i in obj.authors.all():
print(i)
查询张三写过什么书(反向查询)
obj = models.Author.objects.get(name='张三')
for i in obj.book_set.all():
print(i)
''' 正向查询 book_obj.authors.all() 对象.属性
Book ---------------------------------------------> Author
<----------------------------------------------
反向查询 author_obj.book_set.all() 对象.表名小写_set
'''
View Code
基于双下划线的跨表查询
- 类似于连表查询
-

########### 一对一
查询lisi的电话号码(正向查询)
obj=models.Author.objects.filter(name='lisi')
print(obj.values('authorDetail__telephone')[0]['authorDetail__telephone'])
obj = models.AuthorDetail.objects.filter(author__name='lisi').values('telephone')
print(obj)
查询333电话是谁的
obj = models.AuthorDetail.objects.filter(telephone='333')
print(obj.values('author__name'))
obj = models.Author.objects.filter(authorDetail__telephone='333').values('name')
print(obj)
################# 一对多
查询狼道是那个出版社出版的
obj = models.Book.objects.filter(title='狼道').values('publishs__name')
print(obj)
obj = models.Publish.objects.filter(book__title='狼道').values('name')
print(obj)
查询新华出版社出版了什么书
obj = models.Publish.objects.filter(name='新华出版社').values('book__title')
print(obj)
obj = models.Book.objects.filter(publishs__name='新华出版社').values('title')
print(obj)
################ 多对多
解忧杂货店这本书是谁写的
obj = models.Book.objects.filter(title='解忧杂货店').values('authors__name')
print(obj)
obj = models.Author.objects.filter(book__title='解忧杂货店').values('name')
print(obj)
alex写了什么书
obj= models.Author.objects.filter(name='alex').values('book__title')
# print(obj)
obj = models.Book.objects.filter(authors__name='alex').values('title')
print(obj)
############### 进阶的
玄机出版社 出版的书名称及作者的名称
obj = models.Publish.objects.filter(name='玄机出版 社').values('book__title','book__authors__name')
print(obj)
obj = models.Book.objects.filter(publishs__name='玄机出版社').values('title','authors__name')
print(obj)
obj = models.Author.objects.filter(book__publishs__name='玄机出版社').values('name','book__title')
print(obj)
View Code