[英]How can I filter the array contain condition in Django Rest Framework?
我有一个 model REST 列表 API 结果如下:
URL localhost:8000/api/server/list
:
[
{
"id": 320,
"ipv4s": [
{
"id": 1393,
"vlanedipv4networkgroup": {
"name": "52",
"id": 147
},
"ip": "43.224.225.89",
"netmask": "255.255.255.248",
"prefix": 29,
"is_gateway": false,
"is_network_ip": false,
"is_broadcast_ip": false,
"desc": null
},
{
"id": 1394,
"vlanedipv4networkgroup": {
"name": "52",
"id": 147
},
"ip": "43.224.225.90",
"netmask": "255.255.255.248",
"prefix": 29,
"is_gateway": false,
"is_network_ip": false,
"is_broadcast_ip": false,
"desc": null
}
],
"bandwidth": 1000,
"user": null,
"is_applied": true,
"is_finish_task": true,
"simple_hardware_text": "E3-1230v5/16G/256G(SSD)/ ",
"switch_management_server_ip": "43.224.224.29",
"all_disk_dict": {
"total_count": 1,
"disk_type": [
1,
0
],
"total_size": 256
},
"name": "LA-C03-A1",
"desc": "2008",
"cpu": "Intel Xeon E3-1230 v5",
"ram": "Supermicro DDR4___16",
"disk": "Intel SSD___256",
"disk2": null,
"disk3": null,
"disk4": null,
"disk5": null,
"disk6": null,
"disk7": null,
"disk8": null,
"disk9": null,
"disk10": null,
"price": "1000.00",
"pay_time": null,
"expire_time": null,
"ipmi_addr": "172.18.16.197",
"ipmi_account": null,
"ipmi_pwd": null,
"has_intranet": false,
"intranet_ip": null,
"customer_desc": null,
"whmcs_tblorders_id": null,
"recycle_time": null,
"ctime": "2019-01-16T21:27:10.870288+08:00",
"uptime": "2019-06-25T09:30:55.652359+08:00",
"switches": {
"id": 14,
"name": "LA-C03-A",
"desc": "LA-C03-A",
"manage_ip": "192.168.200.17",
"manage_uname": "ADMIN",
"manage_pwd": "ADMIN",
"is_listing": true,
"ctime": "2019-01-16T17:20:00.458601+08:00",
"uptime": "2019-06-12T14:14:19.904123+08:00",
"switch_type": 2,
"routerdevice": 4,
"gatewaydevice": 3
},
"physical_server_model": {
"id": 11,
"cpu": "Intel Xeon E3-1270 v5",
"ram": "Supermicro DDR4___16",
"disk": "Intel SSD___1000",
"price": "2000.00",
"ctime": "2019-01-16T18:42:17.308968+08:00",
"uptime": "2019-01-16T18:42:17.309034+08:00"
},
"switchesport": {
"id": 407,
"name": "LA-C03-A1",
"desc": "",
"bandwidth": 1000,
"ctime": "2019-01-16T21:17:43.695708+08:00",
"uptime": "2019-06-12T14:06:13.571775+08:00",
"switches": 14,
"vlanedipv4networkgroup": null
},
"cabinet": {
"id": 6,
"name": "LA-C05",
"desc": "",
"ctime": "2019-01-16T17:10:16.289312+08:00",
"uptime": "2019-06-12T15:42:48.021362+08:00",
"area_partition": 8
},
"trade_record": null
},
....
]
我可以像这样过滤获取列表:
localhost:8000/api/server/list/?id=320
但是如何过滤获取数组包含?
比如我想获取过滤 ipv4s 的项目的vlanedipv4networkgroup__name = 52
。
"ipv4s": [
{
"id": 1393,
"vlanedipv4networkgroup": {
"name": "52",
"id": 147
},
"ip": "43.224.225.89",
"netmask": "255.255.255.248",
"prefix": 29,
"is_gateway": false,
"is_network_ip": false,
"is_broadcast_ip": false,
"desc": null
},
{
"id": 1394,
"vlanedipv4networkgroup": {
"name": "52",
"id": 147
},
"ip": "43.224.225.90",
"netmask": "255.255.255.248",
"prefix": 29,
"is_gateway": false,
"is_network_ip": false,
"is_broadcast_ip": false,
"desc": null
}
],
如果服务器列表 who's ipv4s item 包含vlanedipv4networkgroup__name=52
,则将其过滤掉。
这是我的列表视图:
class PhysicalServerListAPIView(ListAPIView):
serializer_class = PhysicalServerListSerializer
permission_classes = [IsSuperAdminOrObjEqualsSelf]
pagination_class = CommonPagination
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')
...
filters = {'{}__contains'.format(key): value
for key, value in query_params.items()
if value is not None and key != "page" and key != "page_size"}
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)))
if bandwidth:
qs = qs.filter(Q(switchesport__bandwidth=bandwidth))
# order
qs = qs.annotate(letters=Substr('name', 1, 6), length=Length('name'))
return qs.order_by('pay_time', 'letters', 'length', 'name')
else:
return qs.order_by('pay_time', 'letters', 'length', 'name')
model:
class IPv4Manage(models.Model):
"""
ipv4
"""
ip = models.GenericIPAddressField(help_text="ip")
netmask = models.GenericIPAddressField(help_text="net mask", null=True, blank=True)
prefix = models.IntegerField(help_text="prefix", null=True, blank=True)
is_gateway = models.BooleanField(default=False, help_text="is gateway")
is_network_ip = models.BooleanField(default=False, help_text="")
is_broadcast_ip = models.BooleanField(default=False, help_text="")
ipv4network = models.ForeignKey(to=IPv4NetworkManage, related_name="ipv4s", on_delete=models.CASCADE, help_text="")
vlaned_ipv4network = models.ForeignKey(
to=VlanedIPv4Network, related_name="ipv4s", on_delete=models.SET_NULL, help_text="",
null=True,
blank=True)
desc = models.CharField(null=True, blank=True, max_length=16, help_text="描述")
physical_server = models.ForeignKey(to=PhysicalServer, related_name="ipv4s", on_delete=models.SET_NULL, null=True,
blank=True, help_text="")
ctime = models.DateTimeField(auto_now_add=True)
uptime = models.DateTimeField(auto_now=True)
objects = IPv4ManageManager()
class Meta:
ordering = ['ip'] # Length('ip').asc()
def __str__(self):
return self.ip
def __unicode__(self):
return self.ip
class PhysicalServer(models.Model):
"""
"""
name = models.CharField(max_length=32, unique=True, help_text="")
desc = models.CharField(max_length=256, null=True, blank=True)
cpu = models.CharField(max_length=64, help_text="cpu") # eg:
ram = models.CharField(max_length=64, help_text="mem") # eg: 16GB
disk = models.CharField(max_length=64, null=True, blank=True) # eg: Seagate SATA___1000
...
price = models.DecimalField(max_digits=10, decimal_places=2, default=0.00)
switches = models.ForeignKey(to=Switches)
physical_server_model = models.ForeignKey(to=PhysicalServerModel, null=True, on_delete=models.DO_NOTHING)
switchesport = models.OneToOneField(to=SwitchesPort, related_name="physical_server", on_delete=models.DO_NOTHING)
cabinet = models.ForeignKey(to=Cabinet, on_delete=models.DO_NOTHING, related_name="physical_servers")
user = models.ForeignKey(to=User, related_name="physical_servers", null=True, blank=True, on_delete=models.SET_NULL)
...
intranet_ip = models.GenericIPAddressField(null=True, blank=True)
recycle_time = models.DateTimeField(null=True, blank=True)
ctime = models.DateTimeField(auto_now_add=True)
uptime = models.DateTimeField(auto_now=True)
class Meta:
ordering = ['-cabinet', '-physical_server_model', 'name']
好的,在 DRF 视图中有一个名为 finalize_response 的方法,您应该使用它来覆盖响应。
def finalize_response(self, request, response, *args, **kwargs):
query_parameters = request.GET
response_data = []
if query_parameters.get('ipv4'):
for data in response.data:
if data.get("ipv4"):
response_data.append(data.get("ipv4"))
response.data = response_data
return super(PhysicalServerListAPIView, self).finalize_response(request, response, *args, **kwargs)
好的,所以我基本上所做的就是获取查询参数,然后检查需要响应数据的哪一部分,这里需要 ipv4,因此将返回所有包含 ipv4 dict 的字典。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.