Django如何单次查询获取多个FanGroup关联的所有GenericRelation Fan对象
Django泛型关联单次查询实现方案
场景1:按FanGroup分组展示关联Fan(无N+1查询,总查询次数2次)
该方案可以完美替代循环每个FanGroup单独查Fan的实现,性能提升明显,代码更简洁:
from django.contrib.contenttypes.models import ContentType from django.db.models import Prefetch from .models import FanGroup, Fan def fan_group_list_view(request): # 预加载所有FanGroup关联的Fan,仅执行2次SQL查询 fan_groups = FanGroup.objects.prefetch_related( # 可选:指定只查询Fan需要的字段,减少数据传输 Prefetch('fans', queryset=Fan.objects.only('fan_inventory_id', 'manufacture', 'model')) ).all() return render(request, 'fan_list.html', {'fan_groups': fan_groups})
模板渲染示例:
{% for group in fan_groups %} <div class="fan-group"> <h4>风扇组名称:{{ group.name }}(默认状态:{{ group.default_state|yesno:"开启,关闭" }})</h4> <ul> {% for fan in group.fans.all %} <li>风扇ID:{{ fan.fan_inventory_id }} | 品牌:{{ fan.manufacture }} | 型号:{{ fan.model }}</li> {% endfor %} </ul> </div> {% endfor %}
场景2:严格单次SQL查询获取所有归属FanGroup的Fan
如果要求必须仅执行1次SQL查询,可以通过related_query_name反向关联FanGroup的字段,直接在Fan的查询中完成关联:
from django.db.models import F def all_fan_view(request): # 获取FanGroup对应的ContentType fan_group_ct = ContentType.objects.get_for_model(FanGroup) # 单次查询过滤所有归属FanGroup的Fan,同时关联取出FanGroup的字段 fans = Fan.objects.filter(content_type=fan_group_ct).annotate( group_name=F('fan_controller__name'), group_default_state=F('fan_controller__default_state') ).select_related('content_type').all() return render(request, 'all_fan.html', {'fans': fans})
模板渲染示例:
<ul> {% for fan in fans %} <li>所属风扇组:{{ fan.group_name }} | 风扇ID:{{ fan.fan_inventory_id }} | 品牌:{{ fan.manufacture }}</li> {% endfor %} </ul>
实现原理
你在FanGroup的fans GenericRelation字段中定义了related_query_name='fan_controller',这个参数的作用就是支持从Fan侧反向关联查询FanGroup的字段,不需要额外的查询操作。
内容的提问来源于stack exchange,提问作者Marek
相关产品推荐
相关产品推荐

