如何用Django QuerySet实现指定SQL查询?QuerySet比原生SQL快吗?
问题解答
1. 如何用Django QuerySet实现指定SQL查询
你的原生SQL是从s2_user_subscription左连s2_bot_categories_mappings,取出用户ID、机器人ID和对应的分类ID。基于给定的模型,可通过以下方式实现:
方式一:匹配原生SQL逻辑(直接生成左连接)
利用Django ORM的双下划线关联语法自动生成左连接,同时通过F()表达式保证输出字段名与原生SQL一致:
from django.db.models import F queryset = S2UserSubscription.objects.values( id_s2_users=F('id_s2_users'), id_s2_bot=F('id_s2_bot'), id_s2_bot_categories=F('id_s2_bot__s2botcategoriesmappings__id_s2_bot_categories') )
说明:
id_s2_bot__s2botcategoriesmappings是反向关联的默认名称(因S2BotCategoriesMappings的id_s2_bot字段未指定related_name)。如果之前给该外键设置了related_name(比如related_name='category_mappings'),需改为id_s2_bot__category_mappings__id_s2_bot_categories。
方式二:聚合一对多结果(可选)
如果一个机器人对应多个分类映射,上述QuerySet会返回多行匹配结果(和原生SQL行为一致)。若要将每个订阅的所有分类ID聚合为一个数组(需PostgreSQL支持),可使用:
from django.contrib.postgres.aggregates import ArrayAgg queryset = S2UserSubscription.objects.annotate( category_ids=ArrayAgg('id_s2_bot__s2botcategoriesmappings__id_s2_bot_categories', default=[]) ).values('id_s2_users', 'id_s2_bot', 'category_ids')
2. Django QuerySet是否比原生SQL关联查询更快?
答案是不一定,核心逻辑如下:
- QuerySet本质是将Python代码转换为SQL执行,最终性能取决于生成的SQL质量。如果QuerySet生成的SQL和你手写的原生SQL完全一致,两者性能无差异。
- 若QuerySet生成了冗余SQL(比如不必要的字段查询、多余表连接),或未正确利用索引,此时手写优化后的原生SQL会更快。
- 反之,若你对SQL优化不熟悉,Django ORM通常会生成规范的高效SQL,避免低级错误(如SQL注入),同时提升代码可维护性。
内容的提问来源于stack exchange,提问作者Mahendra
相关产品推荐
相关产品推荐

