三、关联管理器——对象调用
- 前提:
多对多:需要双向均有关联管理器
一对多:只有多的那个类的对象需要关联管理器,也就是
只有反向才有
注意:一对多只能反向
- 语法格式:
正向:属性名称
反向:小写类名+
_set
- 常用方法:
1、add()
add()主要用于多对多,把指定的模型对象添加到关联对象集(对象表)中
注意:add()在一对多,即外键中,只能通过传入对象的方式不能通过传入id的方式
*[]的使用,下面是传入对象的方式
# -*- coding: utf-8 -*- from django.shortcuts import render,HttpResponse from app1_model import models def add_book(request): #books = models.Book.objects.create(title="Python",price=500,publish="Python出版社",pub_date="1970-12-10") book_obj = models.Book.objects.get(id=2) author_list = models.Author.objects.filter(id__gt=2) book_obj.authors.add(*author_list) #将id大于2的作者对象添加到这本书的作者集合中 return HttpResponse("ok")
- 访问测试
查看数据库信息,可以发现id为2的书籍,作者对象的id都是大于2的,即id为2和3的作者
- 传入对象id的方式
# -*- coding: utf-8 -*- from django.shortcuts import render,HttpResponse from app1_model import models def add_book(request): #books = models.Book.objects.create(title="Python",price=500,publish="Python出版社",pub_date="1970-12-10") book_obj = models.Book.objects.get(id=2) #author_list = models.Author.objects.filter(id__gt=2) book_obj.authors.add(*[1,3]) #将id为1和3的作者添加到这本书作者的集合中 return HttpResponse("ok")
- 访问测试
- 查看数据库信息,可以发现id为2的书籍,3个作者都已经添加到了集合中
- 下面是反向,反向应该是
小写表面_set
# -*- coding: utf-8 -*- from django.shortcuts import render,HttpResponse from app1_model import models def add_book(request): #books = models.Book.objects.create(title="Python",price=500,publish="Python出版社",pub_date="1970-12-10") ying = models.Author.objects.filter(name="任盈盈").first() book = models.Book.objects.filter(title="Python教程").first() ying.book_set.add(book) return HttpResponse("ok")
- 访问测试
查看数据库信息,可以看到Python教程(id=1)数据的作者添加了任盈盈(id=3)
2、create()
- 创建一个新的对象,并且同时将它添加到关联对象集之中,返回新创建的对象
# -*- coding: utf-8 -*- from django.shortcuts import render,HttpResponse from app1_model import models def add_book(request): #books = models.Book.objects.create(title="Python",price=500,publish="Python出版社",pub_date="1970-12-10") pub = models.Publish.objects.filter(name="明教出版社").first() wo = models.Author.objects.filter(name="任我行").first() book = wo.book_set.create(title="ORM教程",price=150,pub_date="2012-10-10",publish=pub) print(book,type(book)) return HttpResponse("ok")
- 访问测试
- 查看数据库信息
3、remove()
- 从关联对象集中移除执行的对象,对于
ForeignKey
对象,这个方法尽在null=True
即可以为空时存在,没有返回值 - 先来看一下数据库信息,确定好要删除的行
- 例如要删除书籍2和作者2的行
# -*- coding: utf-8 -*- from django.shortcuts import render,HttpResponse from app1_model import models def add_book(request): #books = models.Book.objects.create(title="Python",price=500,publish="Python出版社",pub_date="1970-12-10") author_obj = models.Author.objects.get(id=2) book_obj = models.Book.objects.get(id=2) author_obj.book_set.remove(book_obj) return HttpResponse("ok")
- 访问测试
查看数据库信息,可以看到已经删除
4、clear()
- 从关联对象集合中移除
所有
对象,删除关联,不会删除对象。对于ForeignKey
对象,这个方法仅在null=True
即可以为空时存在,没有返回值
# -*- coding: utf-8 -*- from django.shortcuts import render,HttpResponse from app1_model import models def add_book(request): #books = models.Book.objects.create(title="Python",price=500,publish="Python出版社",pub_date="1970-12-10") book = models.Book.objects.filter(title="Django教程").first() book.authors.clear() #删除django教程的所有关联 return HttpResponse("ok")
访问测试
查看数据库信息,可以看到Book表中的Django教程行还是存在的,但是关联表book_authors中的Django教程(id=2)的行已经被删除
四、ORM查询
- 基于对象的跨表查询
- 语法:
正向:属性名称
反向:小写类名_set
1、一对多
- 查询主键为3的书籍出版社所在的城市,即正向查询
# -*- coding: utf-8 -*- from django.shortcuts import render,HttpResponse from app1_model import models def add_book(request): #books = models.Book.objects.create(title="Python",price=500,publish="Python出版社",pub_date="1970-12-10") book = models.Book.objects.filter(pk=3).first() res = book.publish.city print(res,type(res)) return HttpResponse("ok")
访问测试
查看终端输出和数据库信息,可以看到是相同的
查询华山出版社出版的书籍名称,即反向
反向的写法:对象.小写类名_set(pub.book_set)可以跳转到关联的表,即书籍表
pub.book_set.all():取出书籍表中的所有书籍对象,在一个QuerySet对象中,遍历取出书籍对象
# -*- coding: utf-8 -*- from django.shortcuts import render,HttpResponse from app1_model import models def add_book(request): #books = models.Book.objects.create(title="Python",price=500,publish="Python出版社",pub_date="1970-12-10") pub = models.Publish.objects.filter(name="华山出版社").first() res = pub.book_set.all() for i in res: print(i.title) return HttpResponse("ok")
访问测试
查看终端输出和数据库信息
2、一对一
- 正向:对象.属性(author.au_detail)可以跳转到关联的表
- 下面查询令狐冲的电话
# -*- coding: utf-8 -*- from django.shortcuts import render,HttpResponse from app1_model import models def add_book(request): #books = models.Book.objects.create(title="Python",price=500,publish="Python出版社",pub_date="1970-12-10") author = models.Author.objects.filter(name="令狐冲").first() res = author.au_detail.tel print(res,type(res)) return HttpResponse("ok")
- 访问测试
- 查看终端输出和数据库信息
查询到所有住址在黑木崖的作者姓名,即反向,一对一的反向,使用对象.小写类名即可,不用加_set
反向:对象.小写类名(addr.author)可以跳转到关联的表
# -*- coding: utf-8 -*- from django.shortcuts import render,HttpResponse from app1_model import models def add_book(request): #books = models.Book.objects.create(title="Python",price=500,publish="Python出版社",pub_date="1970-12-10") addr = models.AuthorDetail.objects.filter(addr="黑木崖").first() res = addr.author.name print(res,type(res)) return HttpResponse("ok")
访问测试
查看终端输出和数据库信息,由于上面查询时使用了first()方法,所以只输出了一个作者名称