Django 笔记6 – 多表查询
Django 系列笔记是笔者学习、实践使用 Django 的相关笔记,大量参考了知了课堂的《Django零基础到项目实战》教程。
参考文档:
Django官方文档(英文)
Django 中文文档
一、一对一
1、概要
- 在实际网站中,可能需要保存用户的许多信息,但是有些信息是不经常用的。如果把所有信息都存放到一张表中可能会影响查询效率,因此可以把用户的一些不常用的信息存放到另外一张表中。用户信息的概要表和详细表就是典型的一对一的关系。
- Django 通过 Field 为 OneToOneField 的字段实现一对一的关系。
2、ORM 模型
class User(models.Model):
"""
用户信息概要表
"""
username = models.CharField(max_length=20)
password = models.CharField(max_length=100)
class UserExtension(models.Model):
"""
用户信息详细表
"""
birthday = models.DateTimeField(null=True)
school = models.CharField(blank=True,max_length=50)
# 设置与 User 表一对一,反向引用名为 extension
user = models.OneToOneField("User", on_delete=models.CASCADE, related_name='extension')
3、查询
正向引用: UserExtension 表中的对象查询 User 表中对应对象的信息
# 查询详细表对象对应的概要信息的指定字段值,格式如下
UserExtension对象.一对一字段名.对应表的列名
# 示例
user_extension = UserExtension.objects.get(id='xx')
user_extension.user.username
反向引用: User 表中的对象查询 UserExtension 表中对应对象的信息
# 查询用户对象对应的详细信息的指定字段值,格式如下
User对象.反向引用名.对应表的列名
# 示例
user = User.objects.get(name='xx')
user.extension.school
二、一对多
1、概要
- 一个文章只能由一个作者编写,但是一个作者可以写多篇文章。作者和文章之间的关系就是典型的一对多的关系。
- Django 通过 Field 为 ForeignKey 的字段实现一对多的关系。
2、ORM 模型
class User(models.Model):
"""
用户信息概要表
"""
username = models.CharField(max_length=20)
password = models.CharField(max_length=100)
class Article(models.Model):
"""
文章信息表
"""
title = models.CharField(max_length=100)
content = models.TextField()
# 设置与 User 表一对多,反向引用名为 articles
author = models.ForeignKey("User", on_delete=models.CASCADE, related_name='articles')
3、查询
正向引用: Article 表中的对象查询 User 表中对应对象的信息
# 查询文章对象对应的作者概要信息的指定字段值,格式如下
Article对象.一对多字段名.对应表的列名
# 示例
article = Article.objects.get(id='xx')
article.user.username
反向引用: User 表中的对象查询 Article 表中对应对象的信息
# 查询用户对象对应的所有文章,格式如下
User对象.反向引用名.all()
# 查询用户对象对应的一篇文章,格式如下
User对象.反向引用名.first()
# 示例
user = User.objects.get(name='xx')
user.articles.all()
# 可以通过遍历 .all() 生成的对象进一步查询到具体的字段名
三、多对多
1、概要
- 一篇文章可以有多个标签,一个标签可以被多个文章所引用。因此标签和文章的关系是典型的多对多的关系。
- Django 通过 Field 为 ManyToManyFiel 的字段实现多对多的关系。
- 在数据库层面 Django 会自动生成一张中间表来关联多对多的两张表。
2、ORM 模型
class Article(models.Model):
"""
文章信息表
"""
title = models.CharField(max_length=100)
content = models.TextField()
# 设置与 Tag 表多对多,反向引用名为 articles
tags = models.ManyToManyField("Tag",related_name="articles")
class Tag(models.Model):
"""
标签表
"""
name = models.CharField(max_length=50)
3、查询
正向引用: Article 表中的对象查询 Tag 表中对应对象的信息
# 查询文章对应的所有标签,格式如下
Article对象.多对多字段名.all()
# 示例
article = Article.objects.get(id='xx')
article.tags.all()
反向引用: Tag 表中的对象查询 Article 表中对应对象的信息
# 查询标签对应的所有文章,格式如下
Tag对象.反向引用名.all()
# 示例
tag = Tag.objects.get(name='xx')
tag.articles.all()
四、related_name 和 related_query_name:
1、related_name:反向引用名
- 默认为:模型名字小写_set
- 可以通过指定 related_name 来自定义反向引用名
- 如果不使用反向引用,那么可以指定related_name=’+’
2、related_query_name:反向查询名
- 默认为:未自定义 related_name 时为模型名小写,自定义 related_name 时与 related_name 一致
- 可以通过指定 related_query_name 来自定义反向引用名
# 使用方法,格式:
User.objects.filter(反向查询名__字段名=value)
# 示例,设:models.ForeignKey("User", on_delete=models.CASCADE, related_query_name='article')
users = User.objects.filter(article__title='abc')
GOOD LUCK!