I have a django model which I want to display via Django Rest framework. I am getting all objects in the model to be displayed via the get_queryset()
. However, I also have a couple of query_params
which will filter out certain objects. This is my main code which is working fine:
class PlanView(generics.ListAPIView):
"""
API endpoint which allows prices to be viewed or edited
"""
serializer_class = PlanSerializer
permission_classes = (IsAuthenticatedOrReadOnly,)
# override method
def get_queryset(self):
//get all objects in Plan model
queryset = Plan.objects.all()
// possible query parameters to be read from url
size = self.request.query_params.get("size", None)
price = self.request.query_params.get("price", None)
if size is not None:
if size == "large":
queryset = queryset.filter(Large=True)
elif size == "small":
queryset = queryset.filter(Large=False)
if price is not None:
queryset = queryset.filter(price=price)
return queryset
with this urlpattern
:
path(r'API/plans', views.PlanView.as_view(), name='prices'),
The only problem is that when I purposefully write the below URL in a browser,
http://127.0.0.1:8000/API/plans?size=sm
which has a bad/misspelled query_param
value, the get_query() code will just ignore it and display the objects as if there are no filters.
I tried to put an else statement such as:
if size is not None:
if size == "large":
queryset = queryset.filter(Large=True)
elif size == "small":
queryset = queryset.filter(Large=False)
else:
return Response({"Error":"bad request"}, status=status.HTTP_400_BAD_REQUEST)
but with this, I get an error message saying:
ContentNotRenderedError at /API/plans
The response content must be rendered before it can be iterated over.
How can I display useful error responses/jsons if a user puts in a wrong parameter value in the API?
You can use ValidationError
from rest_framework.exceptions import ValidationError
# ...
raise ValidationError(detail="size must be either 'large' or 'small'")
DRF catches these exceptions and displays them neatly. It returns a JSON of the form
{
"detail": "size must be either 'large' or 'small'"
}