文章目录
ORM多表操作
创建模型
通过上图关系,来定义一下我们的模型类。
from django.db import models
class Book(models.Model):
title = models.CharField(max_length=32)
price = models.DecimalField(max_digits=5, decimal_places=2)
pub_date = models.DateField()
publish = models.ForeignKey("Publish", on_delete=models.CASCADE)
authors = models.ManyToManyField("Author")
class Publish(models.Model):
name = models.CharField(max_length=32)
city = models.CharField(max_length=64)
email = models.EmailField()
class Author(models.Model):
name = models.CharField(max_length=32)
age = models.SmallIntegerField()
au_detail = models.OneToOneField("AuthorDetail", on_delete=models.CASCADE)
class AuthorDetail(models.Model):
gender_choices = (
(0, "女"),
(1, "男"),
(2, "保密"),
)
gender = models.SmallIntegerField(choices=gender_choices)
tel = models.CharField(max_length=32)
addr = models.CharField(max_length=64)
birthday = models.DateField()
一对多的新增
- 方式一 传对象的形式
def add_book(request):
pub_obj = models.Publish.objects.get(pk=1)
book = models.Book.objects.create(title="独孤九剑", price=140, pub_date="2008-08-23", publish=pub_obj)
return HttpResponse("新增成功!")
- 方式二 传对象的id
def add_book(request):
book = models.Book.objects.create(title="冲灵剑法", price=120, pub_date="2018-08-23", publish_id=pub_obj.pk)
return HttpResponse("新增成功!")
多对多的新增
- 方式一 传对象的形式
def add_book(request):
book_obj = models.Book.objects.get(pk=1)
ling = models.Author.objects.get(pk=4)
ying = models.Author.objects.get(pk=6)
book_obj.authors.add(ling, ying)
return HttpResponse("新增成功!")
- 方式二 传对象id
def add_book(request):
book_obj = models.Book.objects.get(pk=2)
ling = models.Author.objects.filter(name='令狐冲').first()
book_obj.authors.add(ling.pk)
return HttpResponse("新增成功!")
多对多其他常用API:
book_obj.authors.remove() # 将某个特定的对象从被关联对象集合中去除。 ====== book_obj.authors.remove(*[])
book_obj.authors.clear() #清空被关联对象集合
book_obj.authors.set() #先清空再设置
关联管理器(RelatedManager)
"关联管理器"是在一对多或者多对多的关联上下文中使用的管理器。
-
大前提:
- 多对多,双向都有
- 一对多时,对应多的一方才有(出版社的角度), 一对多时,反向才能使用关联管理器
def add_book(request):
# add(obj1[, obj2, ...])方法
author_obj = Author.objects.get(pk=1)
book_obj = Book.objects.get(pk=2)
author_obj.book_set.add(book_obj)
# create(**kwargs)方法
ling = models.Author.objects.get(pk=4)
ling.book_set.create(title="吸星大法", price=110, pub_date="2011-12-12", publish_id=1)
# remove(obj1[, obj2, ...])
book_obj = Book.objects.get(pk=2)
author_obj .book_set.remove(book_obj)
# clear()
# 从关联对象集中移除一切对象。
author_obj = Author.objects.get(id=1)
author_obj.book_set.clear()
#注意这样不会删除对象 —— 只会删除他们之间的关联。
# set()方法
# 先清空,在设置,编辑书籍时即可用到。
book = models.Book.objects.filter(title="独孤九剑").first()
book.authors.set([1, 3])
return HttpResponse("新增成功!")
注意:
对于所有类型的关联字段,add()、create()、remove()和clear(),set()都会马上更新数据库。换句话说,在关联的任何一端,都不需要再调用save()方法。
基于对象的跨表查询
一对多关系
- 正向
查询主键为1的书籍的出版社所在的城市
def query_book(request):
book_obj = models.Book.objects.filter(pk=1).first()
print(book_obj.publish.city)
return HttpResponse("查询成功!")
- 反向
查询华山出版社出版的书籍名
def query_book(request):
pub_obj = models.Publish.objects.filter(name="华山出版社").first()
for book in pub_obj.book_set.all():
print(book.title)
return HttpResponse("查询成功!")
一对一的关系
反向时,直接小写的表名即可(不用_set)
- 正向
查询令狐冲的电话
def query_book(request):
author_obj = models.Author.objects.filter(name="令狐冲").first()
print(author_obj.au_detail.tel)
return HttpResponse("查询成功!")
- 正向
查询所有住址在黑木崖的作者的姓名
def query_book(request):
au_detail_obj = models.AuthorDetail.objects.filter(addr="黑木崖")
for au in au_detail_obj:
print(au.author.name)
return HttpResponse("查询成功!")
多对多的关系
- 正向
查询独孤九剑所有作者的名字以及手机号
def query_book(request):
book_obj = models.Book.objects.filter(title="独孤九剑").first()
for au in book_obj.authors.all():
print(au.name, au.au_detail.tel)
return HttpResponse("查询成功!")
- 正向
查询令狐冲出过的所有书籍的名字
def query_book(request):
au_obj = models.Author.objects.filter(name="令狐冲").first()
for book in au_obj.book_set.all():
print(book.title)
return HttpResponse("查询成功!")
基于双下划线的跨表查询
一对多关系
查询华山出版社出版过的所有书籍的名字与价格(一对多)
- 正向
def query_book(request):
book = models.Book.objects.filter(publish__name="华山出版社").values("title", "price")
return HttpResponse("查询成功!")
- 反向
def query_book(request):
book = models.Publish.objects.filter(name="华山出版社").values("book__title", "book__price")
return HttpResponse("查询成功!")
多对多关系
查询令狐冲出过的所有书籍的名字(多对多)
- 正向
def query_book(request):
book = models.Book.objects.filter(authors__name="令狐冲").values("title")
return HttpResponse("查询成功!")
- 反向
def query_book(request):
book = models.Author.objects.filter(name="令狐冲").values("book__title")
return HttpResponse("查询成功!")
一对一关系
查询令狐冲的手机号
- 正向
def query_book(request):
book = models.Author.objects.filter(name="令狐冲").values('au_detail__tel')
return HttpResponse("查询成功!")
- 反向
def query_book(request):
book = models.AuthorDetail.objects.filter(author__name="令狐冲").values('tel')
return HttpResponse("查询成功!")
连续跨表
查询华山出版社出版过的所有书籍的名字以及作者的姓名
- 正向
def query_book(request):
book = models.Book.objects.filter(publish__name="华山出版社").values('title', 'authors__name')
return HttpResponse("查询成功!")
- 反向
def query_book(request):
book = models.Publish.objects.filter(name="华山出版社").values("book__title", "book__authors__name")
return HttpResponse("查询成功!")