I'm trying to implement this scheme:
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",
}
]
}
]
}
And then be able to GET all alerts nested into a source:
** The source will be unique
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",
}
And POST a single alert into that source:
{
"dns_server": "7.7.2.2",
"ip_addr": "224.110.70.3",
}
My question is: is possible to implement a list/create viewset of a route with parameters?
router.register(r'set_work/(?P<type>.+)/(?P<source>.+)', views.SetWorkViewSet)
In that case, how can I use that parameters in the viewset in order to filter the queryset?
Thank you in advance. Any other approaches will be very welcome, I'm very new to python/django.
Sure you can!
Django REST Framework (DRF) for model viewsets (which I assume you are using) implements standard get_object
and get_queryset
methods. Since you added additional parameters to the url regex, you can reference them via self.kwargs
inside the viewset:
def get_queryset(self):
qs = super(...).get_queryset()
return qs.filter(type=self.kwargs['type'], source=self.kwargs['source'])
This will do the filtering which will make list
work. As for the create
, you will probably need to adjust the serializer in order to use the values from the url kwargs. There are a couple of ways to do that:
add the url kwargs to the data being passed to the serializer when instantiating it
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)
This technically should work however feels a bit hackish to me so I would not recommend this approach.
adjust the validation logic within the serializer to add the url parameters
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)
I personally feel this approach is cleaner even though it leaks a little of information about the viewset to the serializer.
Please note the code is not tested so you will need to do some testing but it should get you started.