在Django Rest Framework中如何过滤含关联数组条件的服务器列表
实现IPv4 VLAN组名称过滤PhysicalServer列表
首先,我们需要通过嵌套关联查询来过滤出包含指定VLAN组名称的IPv4的服务器,同时要注意避免重复结果和优化查询性能。以下是具体的改造步骤:
1. 修改get_queryset方法,添加过滤逻辑
在你的PhysicalServerListAPIView的get_queryset方法中,新增VLAN组名称的参数处理和过滤条件:
def get_queryset(self): query_params = self.request.query_params id_list = get_param_from_query_params(query_params, 'id_list[]', True) sort_param = get_param_from_query_params(query_params, 'sort_param') ip = get_param_from_query_params(query_params, 'ip') server_status = get_param_from_query_params(query_params, 'server_status') # 新增:获取VLAN组名称过滤参数 vlan_group_name = get_param_from_query_params(query_params, 'vlanedipv4networkgroup_name') ... # 生成filters时排除VLAN组参数,避免错误的contains过滤 filters = { '{}__contains'.format(key): value for key, value in query_params.items() if value is not None and key not in ["page", "page_size", "vlanedipv4networkgroup_name"] } qs = PhysicalServer.objects.filter(user=self.request.user).filter(**filters) if id_list: qs = qs.filter(id__in=id_list) if ip: qs = qs.filter(ipv4s__ip=ip).prefetch_related( Prefetch('ipv4s', queryset=IPv4Manage.objects.filter(ip=ip))) # 新增:处理VLAN组名称过滤 if vlan_group_name: # 过滤出至少有一个IPv4属于指定VLAN组的服务器 qs = qs.filter(ipv4s__vlaned_ipv4network__name=vlan_group_name).distinct() # 可选:预取符合条件的IPv4条目,减少数据库查询并优化返回结果 qs = qs.prefetch_related( Prefetch('ipv4s', queryset=IPv4Manage.objects.filter(vlaned_ipv4network__name=vlan_group_name)) ) if bandwidth: qs = qs.filter(Q(switchesport__bandwidth=bandwidth)) # 排序逻辑 qs = qs.annotate(letters=Substr('name', 1, 6), length=Length('name')) return qs.order_by('pay_time', 'letters', 'length', 'name')
2. 关键细节说明
- 嵌套关联查询:
ipv4s__vlaned_ipv4network__name是Django的关联查询语法,依次关联PhysicalServer→IPv4Manage→VlanedIPv4Network的name字段。注意这里用的是模型里的字段名vlaned_ipv4network,对应你API返回中的vlanedipv4networkgroup应该是序列化时的字段重命名,确保关联关系正确即可。 distinct()去重:一个服务器可能有多个符合条件的IPv4条目,直接过滤会返回重复的服务器对象,distinct()可以保证每个服务器只出现一次。- 可选的
Prefetch优化:如果希望API返回的ipv4s数组只包含符合VLAN组条件的条目,就保留Prefetch代码;如果需要返回服务器的所有IPv4(仅过滤服务器本身),可以去掉这部分。
3. 请求使用示例
现在你可以通过以下请求来过滤目标服务器:
GET localhost:8000/api/server/list?vlanedipv4networkgroup_name=52
内容的提问来源于stack exchange,提问作者user7693832
相关产品推荐
相关产品推荐

