This is my Django model:
class M(models.Model):
a = models.IntegerField()
b = models.IntegerField()
This is the serializer:
class MSerializer(ModelSerializer):
class Meta:
model = M
fields = ['a', 'b']
I would like to be able to implement these REST APIs:
127.0.0.1:8000/m/
(GET list of all elements, POST new element)127.0.0.1:8000/m/:id/
(GET details of element with idid
)127.0.0.1:8000/n/:a/m/
(GET all elements with a specifica
field)
So far this is the view and urls that I implemented:
class MViewSet(ModelViewSet):
queryset = M.objects.all()
serializer_class = MSerializer
router = DefaultRouter()
router.register(r'm', MViewSet)
urlpatterns = [
path('', include(router.urls)),
]
However, in this way the third use case is not working. How can I modify my code to make the third case work? I'd prefer to use as few lines of code as possible (i.e., I would like to use some Django built-in functionalities).
CodePudding user response:
Since it look like you want the 3rd endpoint on another root (possibly another app name n
), I'll implement it is a standalone API view, and not as an action on a viewset (although both options are possible)
class FilteredMListView(ListAPIView):
serializer_class = MSerializer
def get_queryset(self):
return M.objects.filter(a=self.kwargs["a"])
Then you register it to the router using:
urlpatterns = [
path("n/<str:a>/m/", FilteredMListView.as_view())
]
CodePudding user response:
For your 3rd case, I would use a ListAPIView
, overriding the get_queryset
method to filter by the passed value for a
. The idea is that when get_queryset
method is invoked, and with as many other filters you'd like to implement, the condition for a
is always present. Since the value for a
will be in the url, it is mandatory, and you always have in in the view's kwargs. Would look like this:
urls.py
router = DefaultRouter()
router.register(r'm', MViewSet)
urlpatterns = [
path('', include(router.urls)),
path('<a>/m', AValuesListApiView.as_view()
]
views.py
class AValuesListApiView(generics.ListAPIView):
queryset = M.objects.all()
serializer_class = MSerializer
def get_queryset(self):
return super().get_queryset().filter(score=self.kwargs["score"])