I am relatively new to the web development and I am writing backend for webapp for practicing chemical elements and compounds and their formulas in our school. I am using Django and Django Rest Framework. I have encountered a dilemma where I can't decide whether to use GET method or POST method. In frontend it requests compounds and elements from the server with specific criteria. In this view, it recieves request with body (criteria), where are values requested_count, used_ids (to exclude already used compounds/elements), requested_groups, requested_elements (to exclude elements which may students don't know). Each value (except count) could be a list with potentially hundreds of items. Then, it filters the database to return the response. I have tested this many times and it is working correctly. My only question is, which method to use in this view. I know that POST should be used when I want to change something in the database and GET to just get query from the database. According to this I should use GET. But I want to send body with that request and that is something what POST typically does. What do you suggest? Thanks
Here is the view code:
class RequestCompoundsView(views.APIView):
serializer_class = RequestCompoundsSerializer
def get(self, request):
serializer = self.serializer_class(data=request.data)
if serializer.is_valid():
# Get the request data from serializer
requested_count = serializer.validated_data.get("count", 10)
used_ids = serializer.validated_data.get("used_ids", [])
requested_groups = serializer.validated_data.get("groups", [])
requested_elements = serializer.validated_data.get("elements", [])
# Find the elements and groups objects
groups, elements = find_requested_groups_elements(
requested_groups, requested_elements
)
# Check if the group and element names are correct
if groups.count() == 0:
context = {"error": "invalid group name"}
return Response(context, status=status.HTTP_400_BAD_REQUEST)
if elements.count() == 0:
context = {"error": "invalid element name"}
return Response(context, status=status.HTTP_400_BAD_REQUEST)
# Make a query and filter it out the database
query = ~Q(id__in=used_ids) & Q(group__in=groups) & Q(elements__in=elements)
samples = (
Compound.objects.filter(query)
.order_by("?")[:requested_count]
.select_related("group")
)
count = Compound.objects.filter(query).count()
# Check if the wanted conditions are correct
if count == 0:
context = {"error": "query returned no results"}
return Response(context, status=status.HTTP_204_NO_CONTENT)
# Return the results
serializer = SendCompoundsSerializer(samples, many=True)
context = {"data": serializer.data, "count": count}
return Response(context, status=status.HTTP_200_OK)
# If there is a problem, return bad request
else:
print(serializer.errors)
context = {"error": "invalid request data"}
return Response(context, status=status.HTTP_400_BAD_REQUEST)
Here are the serializers:
# Serializer for the incomming requests
class RequestCompoundsSerializer(serializers.Serializer):
used_ids = serializers.ListField(child=serializers.IntegerField())
groups = serializers.ListField(child=serializers.CharField())
elements = serializers.ListField(child=serializers.CharField())
count = serializers.IntegerField(max_value=100, min_value=1)
class Meta:
fields = ("used_ids", "groups", "elements", "count")
# Response of the server for the frontend
class SendCompoundsSerializer(serializers.ModelSerializer):
class Meta:
model = Compound
fields = ("id", "formula", "name")
GET
The get method is used to get to from the server. For example, a list of elements, also usually lists can be filtered by a certain criterion, the GET method is enough for this, just pass the parameters to the query-params, for example like this
query-params can also be used for sorting and pagination.
POST
The post method is most often used when you need to send certain data to the server in the body of a form request (if you use django templates), create a record in the database, and the like.
Therefore, in order to decide for yourself what request to send to the server, simply ask yourself the question "what can the client do now?" - if you receive a list/one element, then you need to send GET, if the client needs to send something to you on the server, then POST.
And finally, there is such a rule, if you do not know what request to send, when you are in doubt, then you need to send a POST request, for example in case of logout.