Django数据库连表查询(一对一、一对多、多对多)

1、一对一关系

比如某班级学生表和学生详细信息表
两张表结构如下
class Student(models.Model):
    stu_id = models.AutoField(primary_key=True)
    stu_name = models.CharField(max_length=32)
                               
class StudentDetail(models.Model):
    stu_detail_id = models.AutoField(primary_key=True)
    height = models.PositiveIntegerField(null=True)
    #设置一对一关系
    stu = models.OneToOneField('Student', on_delete=models.CASCADE, to_field='stu_id', null=True)

在这里主表为Student,子表为StudentDetail(即包含外键的表)
通过子表查询主表为正向查询,代码如下

#实例化获取数据
stu = StudentDetail.objects.get(pk=1)
#打印Student表中的stu_name字段
print(stu.stu_name)

通过主表查询子表为反向查询,代码如下
(系统会自动创建一个 类名小写的字段对象)

# 系统会自动创建一个 类名小写的字段对象
stu = Student.objects.get(pk=1)
# 类名字的小写
print(stu.studentdetail.height)

2、一对多关系

一对多关系可如此理解: 一个班级中有多个学生,但一个学生并不同时属于多个班级
此处班级表为“一”,学生表为“多”
class ClassRoom(models.Model):
    cls_id = models.AutoField(primary_key=True)
    cname = models.CharField(max_length=32)
    cdata = models.DateField(auto_now_add=True)

class Student(models.Model):
    stu_id = models.AutoField(primary_key=True)
    stu_name = models.CharField(max_length=32)

    # 一对多设置
    cid = models.ForeignKey(to="ClassRoom", db_column='cls_id')
	
    class Meta:
        db_table = 'student'
    def __str__(self):
        return "%s" % [self.stu_name]

正向查询和一对一相同
反向查询如下
(1、系统会自动创建一个 "类名小写_set"的字段对象)
(2、通过正向查询关键字段+双下划线__+“一”表中的字段)

#第一种方法
class = ClassRoom.objects.get(pk=1)
stu_list = class.student_set.all()
#第二种方法
stu_list = Student.objects.filter(cid__cname="英语")

3、多对多关系

一本书有多个作者,某位作者出版了多本书
class Book(models.Model):
    name = models.CharField(
        max_length=23
    )
    price = models.FloatField()

class Author(models.Model):
    name = models.CharField(
        max_length=30,
        verbose_name="人名"
    )
    books = models.ManyToManyField(
        Book,
        verbose_name="书籍"
    )

通过书籍查找作者(__set方法)

book = Book.objects.all().first() #先获取一本书
authors = book.author_set.all() #通过数据获取

通过作者查找书籍

author = Author.objects.all().first()
books = author.books.all()

查询优化(适用于一对一和一对多)

比如查看所有学生的班级名字
普通查询方法:
student = Student.objects.all()
for i in student:
	print(i.cid.cname)

这样会导致线性的SQL查询,如果对象数量n太多,每个对象中有k个外键字段的话,就会导致n*k+1次SQL查询。可以采用select_related减少查询次数:

student = Student.objects.select_related("cid").all()
for i in student:
	print(i.cid.cname)

只有一次查询

适用于多对多

查看所有作者写的所有书名
books = Author.objects.prefetch_related("books").all()
    for i in books:
        print(i.books.name)
  • 7
    点赞
  • 31
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
Django 一对多查询优化主要包括两个方面:预先加载和选择关联查询。 1. 预先加载(Prefetch) 预先加载是 Django 对象关系映射(ORM)的一个重要特性,用于减少 SQL 查询次数。它可以在查询主模型时,同时查询其关联模型的数据,而不是在后续使用时频繁查询数据库。 例如,一个 `Book` 模型和一个 `Author` 模型之间是一对多的关系,如果要查询所有书籍以及每本书的作者,可以使用 `prefetch_related()` 方法预先加载所有作者的数据: ```python books = Book.objects.all().prefetch_related('authors') ``` 这将通过两个 SQL 查询来实现,第一个查询获取所有书籍的数据,第二个查询获取所有作者的数据,并将其缓存到内存中以供后续使用。这样,当您需要访问每个书籍的作者时,Django 将从缓存中获取数据,而不是执行更多的 SQL 查询。 2. 选择关联查询(Select_related) 选择关联查询是另一个优化一对多查询的方法。它适用于查询与主模型相关联的一个外键模型,例如,如果要查询每本书的出版社名称,可以使用 `select_related()` 方法: ```python books = Book.objects.all().select_related('publisher') ``` 这将通过一个 SQL 查询来实现,查询所有书籍和它们的出版社,并将它们缓存起来。当您需要访问每个书籍的出版社时,Django 将从缓存中获取数据,而不是执行更多的 SQL 查询。 需要注意的是,`select_related()` 适用于外键关系,而 `prefetch_related()` 适用于多对多关系和反向关系。在使用这些方法时,需要考虑到查询的性能和内存消耗。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值