POST 新的嵌套对象

POST new nested object

我正在尝试实施此方案:

http://127.0.0.1:8000/api/get_work/

{
    "type": "dns",
    "source_alerts": [
        {
            "source": "alehop.com",
            "alerts": [
                {
                    "dns_server": "8.8.4.4",
                    "ip_addr": "134.211.190.5",
                },
                {
                    "dns_server": "7.7.2.2",
                    "ip_addr": "224.110.70.3",
                }
            ]
        }
    ]
}

然后能够获取嵌套到源中的所有警报:

** 来源将是唯一的

http://127.0.0.1:8000/api/set_work/dns/alehop.com/

        "alerts": [
            {
                "dns_server": "8.8.4.4",
                "ip_addr": "134.211.190.5",
            },
            {
                "dns_server": "7.7.2.2",
                "ip_addr": "224.110.70.3",
            }

并且 POST 到该来源的单个警报:

        {
            "dns_server": "7.7.2.2",
            "ip_addr": "224.110.70.3",
        }

我的问题是:是否可以实现带参数的路由的 list/create 视图集?

router.register(r'set_work/(?P<type>.+)/(?P<source>.+)', views.SetWorkViewSet)

在那种情况下,如何在视图集中使用该参数来过滤查询集?

提前谢谢你。任何其他方法都将非常受欢迎,我是 python/django.

的新手

当然可以!

用于模型视图集(我假设您正在使用)的 Django REST Framework (DRF) 实现标准 get_objectget_queryset 方法。由于您向 url 正则表达式添加了其他参数,因此您可以通过视图集内的 self.kwargs 引用它们:

def get_queryset(self):
    qs = super(...).get_queryset()
    return qs.filter(type=self.kwargs['type'], source=self.kwargs['source'])

这将执行使 list 工作的过滤。至于 create,您可能需要调整序列化程序才能使用 url kwargs 中的值。有几种方法可以做到这一点:

  1. 在实例化时将 url kwargs 添加到传递给序列化程序的数据中

    class MyViewSet(ViewSet):
        def get_serializer(self, *args, **kwargs):
            # add the url kwargs to request data so that serializer will see it
            self.request.data.update(self.kwargs)
            return super(...).get_serializer(*args, **kwargs)
    

    这在技术上应该可行,但我觉得有点老套,所以我不推荐这种方法。

  2. 调整序列化程序中的验证逻辑以添加 url 参数

    class MySerializer(ModelSerializer):
        class Meta(object):
            model = MyModel
        def to_internal_value(self, data):
            if hasattr(self, 'internal_data') and 'view' in self.context:
                data.update(self.context['view'].kwargs)
            return super(...).to_internal_value(data)
    

    我个人觉得这种方法更简洁,尽管它向序列化程序泄露了一些关于视图集的信息。

请注意代码未经测试,因此您需要进行一些测试,但它应该可以帮助您入门。