Python笔记_50_ORM_多表操作

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()方法。

基于对象的跨表查询
正向>>
>>
<<反向
<<
Book
字段名称
Publish
小写表名+_set
一对多关系
  • 正向
    查询主键为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("查询成功!")
基于双下划线的跨表查询
正向>>
>>
<<反向
<<
Book
字段名称__跨表的字段名称
Publish
小写表名__跨表的字段名称
一对多关系

查询华山出版社出版过的所有书籍的名字与价格(一对多)

  • 正向
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("查询成功!")
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值