ORM------多表操作
上面介绍了单表操作 下面就好比我们的sql语句这只能满足于我们的一些简单的操作不能适应我们更多的需要 所以我们需要用到更多的需求来进行我们的关系的建立以及查找
其实ORM语句就对应着我们的sql语句 表与表之间的关系 无非就是你的
一对一 :好比老公和媳妇 这就是一对一
多对一 :好比出版社和出版的书籍
多对多:好比作者和书籍一本书可以有多个作者联合出版 一个作者可以出版好几本书
这三种关系
一:创建表
创建一对一的关系:OneToOne("要绑定关系的表名")
创建一对多的关系:ForeignKey("要绑定关系的表名")
创建多对多的关系:ManyToMany("要绑定关系的表名") 会自动创建第三张表
并且这个orm和我们的sql虽然是对应的语句最后会通过pymsql进行翻译成对应的sql语句 但是创建的时候还是会有一些细微的差距的 ,比如你orm语句在创建对应的表的类语句的时候并不是和sql一样先创建主表再创建子表的 ,只要你这一次创建的主表和子表都依次建立 那么就不论谁在前 谁在后
from django.db import models # Create your models here. class Book(models.Model): # 不写id的时候数据库会自动给你增加自增id name = models.CharField(max_length= 30) price = models.DecimalField(max_digits=6,decimal_places=3) pub_date = models.DateField() # 一个出版社有多本书,关联字段要写在多的一方 # publish是实例对象关联的出版社对象 # 不用命名为publish_id,因为django为我们自动就加上了_id publish = models.ForeignKey(to = 'Publish',to_field = 'id', on_delete = models.CASCADE) # 这个是orm创建外键的语法 #to = 后面跟的是你要绑定的主表的名字 to_dield 后面跟的是你要绑定的主表的字段 on_delete = models.CASCADE代表你删除的时候可以任意的删除 不会因为绑定了关系而无法删除 authors = models.ManyToManyField(to = 'Author') #这个是自动就帮我们创建了多对多的这个关系的表 def __str__(self):#__str__方法使用来吧对象转换成字符串的,你返回啥内容就打印啥 return self.name class Publish(models.Model): name = models.CharField(max_length = 30) emial = models.CharField(max_length = 40) addd = models.CharField(max_length=30) class Author(models.Model): name = models.CharField(max_length = 30) age = models.IntegerField() # ad = models.OneToOneField(to = 'AuthorDetail', to_field = 'id',on_delete = models.CASCADE) ad = models.OneToOneField(to = 'AuthorDetail', to_field = 'id', on_delete = models.CASCADE) #这个是建立一对一的关系 class AuthorDetail(models.Model): gf = models.CharField(max_length = 30) tel = models.CharField(max_length = 30)
添加信息:
当你对表内添加信息的时候就和sql一样了 你需要对表中的数据进行先对主表进行添加,因为只要主表有了数据你的子表才能选择内容进行选择
author = Author.objects.create(name = '赵云',addr = '中国',Gf_id = 1 ) #这个是会报错的 因为你的外键的列没有能找到对应的表中的值 因为你的主表内没有信息
第一种添加方式(推荐):
book = Book.objects.create(name = '三重门',ptice = 65.4,pub_date = '2003-06-04',publish_id =1 )
直接就是对你的表的内容进行添加
第二种方式可以筛选添加:
# 一对多的添加方式2 # publish必须接受一个对象
获取你的主表的对象 然后通过对象来找到主表的id
可以当作条件来筛选设置
pub = Publish.objects.filter(name = '南方出版社') .first() # 筛选你的name是南方出版社的条件然后找到这个内容 book = Book.objects.create(name = '走西口',ptice = 76.8,pub_date='1997-06-08',publish_id=pub.id) #这个时候个根据你求出的出版社的对象来设置id return HttpResponse(book.name)
book = Book.objects.create(name = '说不清道不尽',ptice = 100,pub_date='2017-08-21',publish = pub) #也可指直接通过对象复制因为你的publish通过orm会自动设置的
book.save()
有人好奇publish=主表对象怎么就可以找到id了 首先你的publish orm再解析语句的时候会自动加上_id这个时候你加不加都可以 然后后面的是对象它会自动的找对象的id
book = Book.objects.create(name = '说不清道不尽',ptice = 100,pub_date='2017-08-21',publish = pub) #也可指直接通过对象复制因为你的publish通过orm会自动设置的 很多人会好奇这是怎么找到的下面的例子你看看: 既然找到了对象那么再找对象的id不就是轻而易举了吗 # book.publish # 与这本书籍关联的出版社对象 # print(book.publish) # print(book.publish_id)
add和set就是通过你的子表和主表关联的字段的名字来进行的使用add和set的因为通过你在子表设置的关系字段名可以找到关系表然后 利用子表调用关系字段名进行设置 就可以添加到关系表内了
添加多对多关系:.add()
add()添加
book = Book.objects.create(name = '人民心论',ptice = 324,pub_date='2000-06-07',publish_id =1 ) ale = Author .objects.filter(name = '赵云').first() #先求出姓名是赵云的作者的名字的对象 zy = Author.objects.filter(name = '赵云龙').first() #再求出姓名是赵云龙的作者的名字的对象 book.authors.add(*[zy,ale]) #通过add来进行对象的添加 设置这个多对多的设置 这个是在你的关系表中创建关系 *是打散迭代添加 #这个但就是对象掉用字段然后直接就创建了关系 因为你的关系表就是类Book中的authors创建的
这个add()添加首先你要找到你的 book这本书指定的的对象然后用add指定这个对象添加
也可以得到所有的对象然后迭代添加到你的信息中
book = Book.objects.filter(name = '三重门').first() #得到书本是三重门的对象 author_list = Author.objects.all() #得到所有的作者对象 book.authors.add(*author_list) #把所有的作者都打散添加给三重门关系表
book.authors.add(1,2) #把book对象的关系设置为和作者1,2关联起来 book.authors.add(*[1,2]) #也可以设置这样的打散关联
set添加:
set添加一次添加多个 比如你要添加的是多个信息就使用set依次把你的信息清空再添加
book_obj.authors.remove()
# 将某个特定的对象从被关联对象集合中去除。 ====== book_obj.authors.remove(*[])
book_obj.authors.clear()
#清空被关联对象集合
book_obj.authors.
set
()
#先清空再设置
set和add区别 add是追加 而set是清空后再添加 (可添加多个) 如果你现在一本书的作者有一个老王 那么你想添加个老赵 这个时候只能用add因为add是追加 set是把以前的清空再追加 如果用set需要写上两个作者
解除绑定的关系:
解除你所设置的表的关系的信息就好比作者和书籍之类的设置要用remove()
清空所有的信息绑定clear()
remove()移除绑定 一个一个的解除:
book = Book.objects.filter(name='三重门').first() # 得到书本是三重门的对象 ale = Author.objects.filter(name='赵云').first() # 先求出姓名是赵云的作者的名字的对象 zy = Author.objects.filter(name = '赵云龙').first() #再求出姓名是赵云龙的作者的名字的对象 book.authors.remove(ale)#解除作者对象是ale和三重门的绑定
这种一个一个的移除有点浪费时间 我们可以用clear()清除所有的绑定
book.authors.clear() #移除所有的作者对象是和三重门的绑定
******
# print(book.publish) # 与这本书籍关联的出版社对象 # print(book.authors.all()) # 与这本书关联的作者对象queryset对象集合<QuerySet [<Author: Author object (1)>, <Author: Author object (2)>]>
print(book.authors) #first.Author.None 因为是多对多你的 对象可能有很多一个无法求出 所以必须用all()
print(type(book.authors)) #类型是class
print(book.authors) #first.Author.None 因为是多对多你的 对象可能有很多一个无法求出 所以必须用all()
print(type(book.authors)) #类型是class
基于对象跨表查询(子查询): 切记 下面是的基于对象的查询
一对多:
正向查询(按照字段):关联属性在book表中,所以book对象找关联出版社对象,正向查询
反向查询(按照表名):关联属性在book表中,所以publish对象找关联书籍,反向查询
按字段:.publish
book ------------------ > publish
<--------------------
按表名小写_set.all() publish_obj.book_set.all()
set.all()主表可以通过子表的表名小写之后来找到自己所需要的信息
print(book.publish.name) #查询book对象的出版社的名字 根据字段来查找
print(book.publish) #Publish object (1)
首先你通过book.publish 找到了关联的报社的这个对象 然后找到了名字
上面就好比这样:
book = Book.objects.filter(name = '三重门').first() #先找到这个三重门的对象
publish_id = book.publish_id #找到这个三重门的关联的出版社的id
publish = Publish.objects.filter(id = publish_id).first() # 通过这个id找到这个出版社的对象
print(publish.name)
书籍对象_set.add()
打印所有的大中国出版社出版的书籍:
publish = Publish.objects.filter(name = '大中国出版社').first() book1 = Book.objects.filter(publish_id = publish) for i in book1: print(i.name)
简便写法用set()
publish = Publish.objects.filter(name = '大中国出版社').first()
ret = publish.book_set.all() #用任意书籍队形调用_set.all() 就可以求出所有的这个出版社的出版书籍
for i in ret:
print(i.name)
多对多:
多对多:
正向查询(按照字段):关联属性在book表中,所以book对象找关联作者集合,正向查询
反向查询(按照):关联属性在book表中,所以author对象找关联书籍,反向查询
正 按字段:.authors.all()
book ------------------------- > author
author <------------------------- book
反 按表名小写_set.all() author_obj.book_set.all()
通过你的子表写小写之后调用set来查找
set.all()主表可以通过子表的表名小写之后来找到自己所需要的信息
这个是求书籍说不清道不尽的作者 book = Book.objects.filter(name='说不清道不尽').first() # 得到书本是三重门的对象 aut = book.authors.all().values('name') print(aut)
因为你的book.authors就能通过你的字段找到你所有的作者的关联的对象那么字然也能找到你的 所有的对象
这里的_set.all()也只是可以通过子表中的任意一个对象都可以找到主表所需要的信息
查找作者赵云出版所有的书籍
book = Book.objects.filter(name='说不清道不尽').first() # 得到书本是三重门的对象
al = Author.objects.filter(name = '赵云').first() ret = al.book_set.all().values('name') print(ret)
一对一:
正向查询:关联属性在author表中,所以author对象找关联作者详细信息对象,正向查询
反向查询:关联属性在author表中,所以authordetail对象找关联作者对象,反向查询
正向查询: 表名.关联表名.字段信息
反向查询: 表名.表名_set.字段信息
正 按字段:.Gf 这个Gf是你的一对一的字段
author ------------------------- > authordetail
<-------------------------
反 按表名小写 authordetail_obj.author
主表可以通过子表的表名小写之后来找到自己所需要的信息
查找作者赵云的女朋友: al = Author.objects.filter(name = '赵云').first() #通过你的 子表内的关联的字段找到你的 作者关联的Gfirend表中的对象的名字 print(al.Gf.name)
是封装了你的子表小写之后的对象然后调用set或者内容来进行的求取