繁体   English   中英

如何在 Django Rest 框架中过滤数组包含条件?

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM