1、. ORM表和表之间的关系 一、 一对多 --> 外键(ForeignKey) 二、 多对多 --> 另一张关系表(ManyToManyField) 1. 三种方式 1. 本身创建第三张关系表,外键分别关联两个表 1. 优势 1. 能够扩充第三张关系标的字段 2. 缺点 1. 本身作连表查询 3. 建表例子 class Book(models.Model): title = models.CharField(max_length=12) class Author(models.Model): name = models.CharField(max_length=12) # 1. 多对多第一种建立方式:本身建立第三张关系表 class Author2Book(models.Model): id = models.AutoField(primary_key=True) author_id = models.ForeignKey(to='Author') book_id = models.ForeignKey(to='Book') price = models.IntegerField() # 能够本身扩充须要的字段 2. 经过ORM内置的ManyToManyField,自动建立第三张关系表 1. 优势 1. 提供了不少连表操做的快捷方法--> all(), add(), set(), clear(), remove() 2. 缺点 1. 没法扩展第三张关系表 3. 建表例子 class Book(models.Model): title = models.CharField(max_length=12) class Author(models.Model): name = models.CharField(max_length=12) books = models.ManyToManyField(to='Book') # 字段就这些,没法扩充其余字段 3. 本身建立第三张关系表,经过ManyToManyField关联 1. 优势: 1. 既可以使用多对多查询的快捷方法all()(只能用all,不能使用add,set等),还可以本身扩展第三张关系表的字段 2. 建表例子 class Book(models.Model): title = models.CharField(max_length=12) class Author(models.Model): name = models.CharField(max_length=12) # 告诉ManyToManyField经过(through)Author2Book这张表进行关联,不使用ORM自动建立的第三张表,而是使用我本身建立的表 # through_fields告诉ORM经过哪几个字段进行多对多关联 books = models.ManyToManyField(to='Book', through='Author2Book', through_fields=('author', 'book')) # 1. 多对多第三种建立方式:本身建立第三张关系表,此时外键不须要添加_id了,由于ORM会默认帮你在外键后面加_id class Author2Book(models.Model): id = models.AutoField(primary_key=True) author = models.ForeignKey(to='Author') book = models.ForeignKey(to='Book') price = models.IntegerField(null=True) # author_id和book_id要联合惟一 class Meta: unique_together = (('author', 'book'),) 3. 操做例子 # 多对多的第三张方式也支持all查询 author_obj = Author.objects.first() # 第一个做者的全部书籍 ret = author_obj.books.all() # 给第一个做者添加一本书 # author_obj.books.add(4) # 报错 Author2Book.objects.create(author_id=1, book_id=4) 2. 之后该用哪一种? 1. 当第三张关系表中不须要其余额外字段的时候,咱们就用默认ManyToManyField就能够了 2. 当第三张关系表中须要额外的字段时,咱们就要用第三种方式,本身创建第三张关系表而且用ManyToManyField关联 三、 一对一 --> OneToOneField 0. 用法和外键同样 1. 当一张表里的字段很是多,而且某几个字段的查询频率远远大于其余字段的时候 2. 把经常使用字段单独拆成一张表,查询的时候更快捷! 3. 当两张表创建了一对一关系后,就不能再关联其余表了 4. 建表例子 class Author(models.Model): name = models.CharField(max_length=12) # 姓名 gender = models.SmallIntegerField(choices=((1, '男'), (2, '女'), (3, '保密')), default=3) # 性别 phone = models.CharField(max_length=11, unique=True) # 手机 email = models.EmailField() # 邮箱 info = models.OneToOneField(to='AuthorInfo') # 详细信息,一对一 # 做者详细信息表 class AuthorInfo(models.Model): birthday = models.DateTimeField() # 生日 city = models.CharField(max_length=12) # 住址 is_marry = models.BooleanField() # 婚否 income = models.BigIntegerField() # 收入 5. 查询例子 # 一对一查询,查询第一个做者的住址 author_obj = Author.objects.first() ret = author_obj.info.city 2、 ORM关联查询 1、 基于对象的查询 0. 建表 class Publisher(models.Model): id = models.AutoField(primary_key=True) name = models.CharField(max_length=20) addr = models.TextField() date = models.DateField() # 成立日期 def __str__(self): return self.name class Book(models.Model): id = models.AutoField(primary_key=True) title = models.CharField(max_length=20) price = models.DecimalField(max_digits=6, decimal_places=2) isbn = models.CharField(max_length=20, unique=True) # 书籍的惟一编号 publisher = models.ForeignKey(to='Publisher', on_delete=models.CASCADE) def __str__(self): return self.title class Author(models.Model): name = models.CharField(max_length=12) # 姓名 gender = models.SmallIntegerField(choices=((1, '男'), (2, '女'), (3, '保密')), default=3) # 性别 phone = models.CharField(max_length=11, unique=True) # 手机 email = models.EmailField() # 邮箱 books = models.ManyToManyField(to='Book') # 做品 info = models.OneToOneField(to='AuthorInfo') # 详细信息 # 做者详细信息表 class AuthorInfo(models.Model): birthday = models.DateTimeField() # 生日 city = models.CharField(max_length=12) # 住址 is_marry = models.BooleanField() # 婚否 income = models.BigIntegerField() # 收入 1. 正向查 对象.关联字段.属性 # 查询第一本书关联的出版社名称 book_obj = Book.objects.first() ret = book_obj.publisher.name print(ret) 2. 反向查 1. 默认不设置related_name属性 1. 查找的对象是多个的时候(一对多或多对多时) publisher_obj.book_set.all() 2. 查找的对象时一个的时候(一对一) author_info_obj.author.name 3. 例如 # 一对多查询(须要给反向查询的表加_set) # 查询第一本书关联的出版社名称(正向查) book_obj = Book.objects.first() ret = book_obj.publisher.name print(ret) # 查询明哥出版社出版的全部书(反向查) publisher_obj = Publisher.objects.get(name='明哥出版社') # 反向查找(多个) .表名_set ret = publisher_obj.book_set.all() print(ret) # 一对一查询(不须要给反向查询的表加_set) # 查询id=1的做者婚否(正向查) author_obj = Author.objects.first() ret = author_obj.info.is_marry print(ret) # 查找住在深圳的那个做者姓名(反向查) authorinfo_obj = AuthorInfo.objects.get(city='深圳') ret = authorinfo_obj.author.name print(ret) 2. 设置related_name='books'属性(publisher = models.ForeignKey(to='Publisher', related_name='books')) # 查询明哥出版社出版的全部书 publisher_obj = Publisher.objects.get(name='明哥出版社') publisher_obj.books.all() 二、 基于QuerySet的查询(__表示跨表查询) 1. 正向查 Book.objects.filter(id=1).values_list('publisher__name') 2. 反向查 1. 默认不设置related_name属性,默认就用类名的小写 Publisher.objects.filter(id=1).values_list('book__price') 2. 设置related_name='books'属性 Publisher.objects.filter(id=1).values_list('books__price') 3. related_query_name = 'hello' 在关联的字段参数设置了related_query_name = 'hello'后,反向查找就不须要使用表名,而是直接使用"hello" 3. 例子 # 热身:普通的values的使用 # 查询第一本书的名称 ret = Book.objects.filter(id=1).values('title') print(ret) # 使用:外键基于QuerySet跨表查询 # 查询第一本书关联的出版社名称(__表示跨表查询)(正向查找) # valuse('publisher')表示经过外键找到了publisher表,__表示跨表取到publisher表的字段的值 ret = Book.objects.filter(id=1).values('publisher__name') print(ret) # 反向查找 # 查询id=1的出版社的全部书的名称和价格 ret = Publisher.objects.filter(id=1).values_list('book__title', 'book__price') print(ret) # 一对一基于QuerySet跨表查询 # 查询id=1的做者婚否(正向查找) ret = Author.objects.filter(id=1).values('info__is_marry') print(ret) # 查找住在深圳的做者的姓名(反向查找) ret = AuthorInfo.objects.filter(city='深圳').values('author__name') print(ret) # 多对多基于QuerySet跨表查询 # 查询id=1的做者关联的全部数据的名称和价格(正向查找) ret = Author.objects.filter(id=1).values('books__title', 'books__price') print(ret) # 查找id=1的做者的名字(反向查找) ret = Book.objects.filter(id=1).values('author__name') print(ret) # 链式查询 # 查找id=1的书的做者的城市 ret = Book.objects.filter(id=1).values('author__info__city') print(ret)