Use as a method in a ViewSet
donatogr opened this issue · comments
Is it possibile to extend a standard DRF ViewSet with a method implementing a DRP PandasView?
I'm also interested in this - or just a way to route extra actions when having a pandasviewset.
http://www.django-rest-framework.org/api-guide/routers/#routing-for-extra-actions
Eg what I'd like to do:
/api/buildings
/api/buildings/1/doors --> give a csv with all doors for a specific building
If I use a ModelViewSet (standard) this will work (returning json) when using
@action(detail=True)
def doors(self, request, pk):
inside the viewset. If I change the viewset to a PandasViewset, it seems these actions no longer work.
Answering myself :
You can achieve this by using nested routing, with the drf-nested-routing package.
Register a nested router:
# urls.py
from rest_framework_nested import routers
building_router = routers.NestedSimpleRouter(building, 'building', lookup='building')
building_router.register('doors', views.DoorsViewset, base_name='building-doors')
And add a view:
class DoorsViewset(PandasViewSet):
def get_queryset(self):
print (self.kwargs)
queryset = Doors.objects.filter(cable_id=self.kwargs['building_pk'])
return queryset
serializer_class = DoorsSerializer
Since most of the work happens in the serializer and renderers, you can also do this without PandasView
/PandasViewSet
. One option would be to override get_renderers()
and explicitly set list_serializer_class
, something like this:
class DoorSerializer(ModelSerializer):
class Meta:
list_serializer_class = PandasSerializer
class BuildingViewSet(ModelViewSet):
def get_renderers(self):
if self.action == 'doors':
return [PandasCSVRenderer(), ...]
else:
return super().get_renderers()
@action(detail=True)
def doors(self, request, pk):
queryset = Doors.objects.filter(...)
return DoorSerializer(queryset, many=True).data
I added some more information to the README.