Django反向查询已缓存QuerySet获取指定卖家图书免二次查询语法
问题解决方案
先修正初始查询的错误
你原来的写法存在两个核心问题:
select_related仅支持正向ForeignKey、一对一关联的连表查询,你场景中Seller到Genre、Genre到Book都是反向一对多关联,必须用prefetch_related做预加载才能一次性拉取所有关联数据- 原查询仅通过
values('name')取了Seller的名称字段,没有包含关联的分类、图书信息,无法后续筛选对应卖家的图书
方案1:用内存中的Django查询集筛选(无需额外访问数据库)
首先修正初始查询,一次性预加载所有三级关联数据到内存:
from django.db.models import Prefetch # 一次性拉取Seller、关联的所有Genre、Genre关联的所有Book到内存 sellers = Seller.objects.prefetch_related( Prefetch('genre', queryset=Genre.objects.prefetch_related('book')) ).all()
筛选指定卖家的图书时直接从内存对象中读取,不会触发新的数据库查询:
# 取第一个卖家的所有图书 seller1_name = seller_df['name'].iloc[0] # 从已加载的sellers中过滤对应卖家,不会查库 seller1 = next(s for s in sellers if s.name == seller1_name) seller1_books = [book for genre in seller1.genre.all() for book in genre.book.all()] # 取最后一个卖家的所有图书 seller_last_name = seller_df['name'].iloc[-1] seller_last = next(s for s in sellers if s.name == seller_last_name) seller_last_books = [book for genre in seller_last.genre.all() for book in genre.book.all()]
方案2:用pandas DataFrame筛选(无需额外访问数据库)
先生成包含所有三级关联信息的DataFrame,查询时就把所有需要的字段取出:
# 拉取所有三级关联的字段数据 sellers_raw = Seller.objects.values( 'name', 'genre__name', 'genre__book__name' ).order_by('name') # 生成带完整信息的DataFrame seller_df = pd.DataFrame(list(sellers_raw)) seller_df.columns = ['seller_name', 'genre_name', 'book_name']
后续直接基于DataFrame做过滤即可:
# 取第一个卖家的所有图书 seller1_name = seller_df['seller_name'].iloc[0] seller1_books = seller_df[seller_df['seller_name'] == seller1_name]['book_name'].dropna().unique().tolist() # 取最后一个卖家的所有图书 seller_last_name = seller_df['seller_name'].iloc[-1] seller_last_books = seller_df[seller_df['seller_name'] == seller_last_name]['book_name'].dropna().unique().tolist()
内容的提问来源于stack exchange,提问作者Tristan Tran
相关产品推荐
相关产品推荐

