之前讲了一下单表查询的用法,今天来讲下多表查询的用法。
Part1:创建表,生成表
# models.py from django.db import models # 作者详情表 class AuthorDetail(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() author_detail = models.OneToOneField(to='AuthorDetail', to_field='nid', on_delete=models.CASCADE, null=True) # 作者表和作者详情表一对一 # 出版社表 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, default='abc') publishDate = models.DateField(default=2020-10-20) price = models.DecimalField(max_digits=5, decimal_places=2, default=2) publish = models.ForeignKey(to='Publish', to_field='nid', on_delete=models.CASCADE, null=True) # 书和出版社表多对一 authors = models.ManyToManyField(to='Author')
models写完以后还是老规矩,执行python manage.py makemigrations 在执行python manage.py migrate ,执行完以后你就会发现数据库中生成了对应的models里面的表了
Part2:造数据
首先给publish表新增数据,同样的新增一个视图函数,在视图函数中添加数据
from django.shortcuts import render from django.http import HttpResponse from showOrmCase.models import * # Create your views here. def show(request): Publish.objects.create(name='上海出版社', city='上海', email='18823@163.com') Publish.objects.create(name='南京出版社', city='南京', email='12312@163.com') return HttpResponse('OK')
执行一下视图函数,查看数据库
Publish表数据造好以后,就可以去造和这个表关联的表数据了,通过models显而易见Book(多)和Publish(一)进行了一对多的关联
一对多和一对一添加数据准则:给关联字段赋值,Book表中的关联字段就是publish_id
# model.py from django.http import HttpResponse from showOrmCase.models import * # Create your views here. def show(request): Book.objects.create(title='人与自然', publishDate='2012-10-14', price=200, publish_id=1) Book.objects.create(title='三国演义', publishDate='2012-08-14', price=150, publish_id=1) Book.objects.create(title='红楼梦', publishDate='2012-10-20', price=350, publish_id=2) return HttpResponse('OK')
执行接口后数据就生成了
按同上道理,在author和authordetail也分别添加上数据
那么问题来了,现在4个表的数据都加好了,还剩一个book_authors这张表,这张表是Book表和Authors多对多关联生成的,这个时候就要用到django自带的接口了
from django.http import HttpResponse from showOrmCase.models import * # Create your views here. def show(request): alex = Author.objects.get(name='alex') leogao = Author.objects.get(name='leogao') # 绑定多对多的接口 book = Book.objects.get(nid='1') book.authors.add(alex, leogao) # 一张表的对象.另一张表.add(另一张表的对象) return HttpResponse('OK')
此时执行视图函数,book_authors就有数据了
还有另一种写法
from django.http import HttpResponse from showOrmCase.models import * # Create your views here. def show(request): alex = Author.objects.get(nid='1') leogao = Author.objects.get(nid='2') # 绑定多对多的接口 book = Book.objects.get(nid='2') book.authors.add(1, 2) # 这边也可以写nid
执行接口查看数据库
比如我们想把刚才绑定的数据分开怎么搞呢,这边django也提供了接口
from django.shortcuts import render from django.http import HttpResponse from showOrmCase.models import * # Create your views here. def show(request): alex = Author.objects.get(nid='1') leogao = Author.objects.get(nid='2') # 解除多对多 book = Book.objects.get(nid='2') book.authors.remove(1, 2)
执行接口,查看数据库刚才的第二本书就没了(ps:将remove改成clear时就把所有的数据都清除了)
新增完数据,接下来就是查询了。
Part3:查询
1.基于对象查询
一对多:
''' 一对多 正向查询:按字段 反向查询:表名小写_set.all() book_obj.publish obj Book(关联属性:publish)-------------------->Publish <-------------------- publish_obj.book_set.all() # querySet '''
from django.http import HttpResponse from showOrmCase.models import * # Create your views here. def analyse(request): # 正向查询:查询三国演义这本书的出版社的名字 name = Book.objects.filter(title='三国演义').first().publish.name print('出版社名字', name) # 反向查询:查询上海出版社出版过的书籍名称 name = Publish.objects.filter(name='上海出版社').first().book_set.all() for i in name: print('书籍名称', i.title) return HttpResponse('OK')
执行视图函数,得到下图结果
多对多:
''' 多对多 正向查询:按字段 反向查询:表名小写_set.all() book_obj.authors Book(关联属性:author)-------------------->Author <-------------------- author_obj.book_set.all() # querySet ''' from django.http import HttpResponse from showOrmCase.models import * # Create your views here. def analyse(request): # 正向查询: 查询三国演义这本书的所有作者的名字 author_name = Book.objects.filter(title='三国演义').first().authors.all().values('name') for i in author_name: print('作者名字', i['name']) # 反向查询: 查询alex出版过的所有书籍名称 book_name = Author.objects.filter(name='alex').first().book_set.all().values('title') for key in book_name: print('书籍名称', key['title']) return HttpResponse('OK')
执行视图函数,得到下图结果
一对一:
''' 一对一 正向查询:按字段 反向查询:表名小写 author.obj.authordetail Author(关联属性:authordetail)-------------------->Authordetail <-------------------- authordetail_obj.author # obj ''' from django.http import HttpResponse from showOrmCase.models import * # Create your views here. def analyse(request): # 正向查询: 查询alex的手机号 phone = Author.objects.filter(name='alex').first().author_detail.telephone print('手机号', phone) # 反向查询:查询手机号为22222的作者的姓名和年龄 author_name = AuthorDetail.objects.filter(telephone='22222').first().author print('名字', author_name.name) print('年龄', author_name.age) return HttpResponse('OK')
执行视图函数,得到下图结果
2.基于双下划线跨表查询(join)
准则:正向查询按字段,反向查询按表名小写来告诉ORM引擎join哪张表
一对多:
# 正向查询:查询红楼梦这本书的出版社的名字 publish_name = Book.objects.filter(title='红楼梦').values('publish__name') print('正向查询名字:', publish_name) # 反向查询 publish_name_two = Publish.objects.filter(book__title='红楼梦').values('name') print('反向查询名字:', publish_name_two)
执行视图函数,得到下图结果
多对多:
name = Book.objects.filter(title='三国演义').values('authors__name') print(name) # 反向 name_two = Author.objects.filter(book__title='三国演义').values('name') print(name_two)
执行视图函数,得到下图结果
一对一:
# 对一正向查询: 查询alex的手机号 phone = Author.objects.filter(name='alex').values('author_detail__telephone') print(phone) phone_two = AuthorDetail.objects.filter(author__name='alex').values('telephone') print(phone_two)
执行视图函数,得到下图结果
以上就是常用的多表查询方法