Django——关于related查找

本文深入探讨Django ORM中的select_related与prefetch_related函数,详细解析如何优化一对多、多对多关系的数据查询,减少SQL执行次数,提高数据加载效率。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

class City(models.Model):
	city_name = models.CharField(verbose_name='城市名',max_length=20)
	def __unicode__(self):
		return self.city_name
	
class Author(models.Model);
    name = models.CharField(verbose_name='作者', max_length=10)
	living = models.Foreignkey(City)
	def __unicode__(self):
		return self.name
	
class Book(models.Model):
    author = models.ForeignKey(Author, related_name='author_book')
    title = models.CharField(verbose_name='书名', max_length=10)
    pubtime = models.DateField(verbose_name='出版时间')
    def __unicode__(self):
		return self.title
related_name属性

查找作者下的所有书籍

  • 常规反向查找
author = Author.objects.filter(name="金庸")
book = author.book_set.all()	# 子表name+_set()
  • related_name反向查找
person.author_books.all()
select_related函数 >> select_related官方文档解释

查找某本书籍的一系列信息

  • 常规方法查找
book = Book.objects.filter(title='雪中悍刀行')	# title,pubtime
author = book.author							# name
city = author.living							# city_name
  • select_related方法查找
 books = Book.objects.select_related(author_living).filter(title='雪中悍刀行')

select_related在查询中,执行的sql语句使用了join的方法,通过一次查询获得所有结果
未指定的外键不会添加到查询结果中
不指定外键会查询次数会根据外键的数量与deep的增加而增加
所以
select_related主要针一对一和多对一关系进行优化。
可以通过可变长参数指定需要select_related的字段名。也可以通过使用双下划线“__”连接字段名来实现指定的递归查询。没有指定的字段不会缓存,没有指定的深度不会缓存,如果要访问的话Django会再次进行SQL查询。
也可以通过depth参数指定递归的深度,Django会自动缓存指定深度内所有的字段。如果要访问指定深度外的字段,Django会再次进行SQL查询。
也接受无参数的调用,Django会尽可能深的递归查询所有的字段。但注意有Django递归的限制和性能的浪费
~Django >= 1.7,链式调用的select_related相当于使用可变长参数。Django < 1.7,链式调用会导致前边的select_related失效,只保留最后一个~

prefetch_related函数 >> prefetch_related官方文档解释

查找是18年以后发表的书的信息

  • 常规查找
books = Book.object.filter(pubtime_gt=start_time)	# 查找符合条件的书籍
for b in books:
	book_author = b.author									# 查找书籍对象的author对象
	author_city = book_author.city							# 查找author对象的city对象
  • prefetch_related查找
start_time = datetime.datetime.strptime("20180101","%Y%m%d")
books = Book.object.filter(pubtime_gt=start_time).prefetch_related('author_city')
for b in books:
	print b.author									# 这里的author不需要再次查询数据库
	print b.city

prefetch_related与select_related的目的都是为了减少sql查询,降低资源消耗。不同的是select_related主要针对于一对多,一对一。而prefetch_related针对于多对多,多对一。
Prefetch对象对字段指定的方式和prefetch_related中的参数相同,都是通过双下划线连接的字段名完成的。
~可以通过 queryset 参数手动指定prefetch使用的QuerySet。~
~可以通过 to_attr 参数指定prefetch到的属性名。~

### 使用 Django、MySQL 和 Vue 构建有声图书网站的最佳实践 #### 项目初始化与环境配置 为了启动一个基于Django和Vue的有声图书网站,需先设置好开发环境。这包括但不限于安装Python解释器以及确保所有必要的Django依赖库已就绪[^3]。 对于数据库的选择,在此案例中选用了MySQL作为后端存储解决方案,并通过Navicat这类工具来进行管理和维护工作。此外,还需注意版本兼容性问题;例如,文中提到使用了特定版本组合——Python 3.7.7搭配MySQL 5.7。 #### 后端开发 (Django) ##### 创建并配置Django应用 一旦环境准备完毕,则可着手建立新的Django工程及其内部的应用程序组件。考虑到项目的特殊需求(即提供在线听书服务),应当定义相应的数据模型来表示书籍信息、章节详情等内容实体。这些都将被保存至预先设定好的MySQL实例之中。 ```python from django.db import models class Book(models.Model): title = models.CharField(max_length=200) author = models.CharField(max_length=100) class Chapter(models.Model): book = models.ForeignKey(Book, on_delete=models.CASCADE) content_url = models.URLField() # 假设音频文件托管于外部CDN或云盘 ``` 上述代码片段展示了两个简单的ORM类映射关系,用于描述一本书籍与其所属各章节之间的关联形式。 ##### API接口设计 为了让前端能够顺利获取到所需的数据资源,必须精心规划RESTful风格的服务端点。借助`django-rest-framework`这样的第三方包可以帮助简化这一过程,从而使得开发者可以专注于业务逻辑本身而非底层通信细节。 #### 前端开发 (Vue.js) ##### 用户界面构建 在完成了基础架构之后,接下来就是打造直观易用的操作面板供访客浏览及收听电子读物之用了。这里推荐运用现代JavaScript框架之一—Vue.js 来完成这项任务。其声明式的语法糖特性极大地提高了编码效率的同时也降低了学习曲线[^4]。 利用HTML/CSS/JS编写静态页面元素,再配合Vue指令实现动态效果,比如加载进度条显示或是播放控制按钮等功能部件。与此同时,还可以考虑引入Element UI等UI库进一步美化整体外观样式。 ##### 客户端请求处理 最后一步便是让前后两端之间建立起有效的联系渠道。通常来说会采用AJAX异步调用来发起HTTP GET/POST 请求并与远端API进行交互。当然也可以探索WebSocket长连接机制以支持更加复杂的场景需求,不过对于本项目而言前者已经足够胜任了。 ```javascript axios.get('/api/books/') .then(response => { this.books = response.data; }) .catch(error => console.log(error)); ``` 这段脚本示范了怎样从服务器拉取最新发布的书籍列表并将结果显示给当前用户查看。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值