Должен ли я использовать GET или POST для запроса с телом в DRF?
Я относительно новичок в веб-разработке и пишу backend для webapp для практических занятий по химическим элементам и соединениям и их формулам в нашей школе. Я использую Django и Django Rest Framework. Я столкнулся с дилеммой, когда не могу решить, использовать ли метод GET или метод POST. Во фронтенде он запрашивает соединения и элементы с сервера с определенными критериями. В этом представлении он получает запрос с телом (критерии), где есть значения requested_count, used_ids (чтобы исключить уже использованные соединения/элементы), requested_groups, requested_elements (чтобы исключить элементы, которые могут быть неизвестны студентам). Каждое значение (кроме count) может быть списком с потенциальными сотнями элементов. Затем он фильтрует базу данных, чтобы вернуть ответ. Я тестировал это много раз, и все работает правильно. Мой единственный вопрос заключается в том, какой метод использовать в этом представлении. Я знаю, что POST следует использовать, когда я хочу изменить что-то в базе данных, а GET - чтобы просто получить запрос из базы данных. В соответствии с этим я должен использовать GET. Но я хочу отправить тело запроса, а это то, что обычно делает POST. Что вы можете посоветовать? Спасибо
Вот код представления:
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)
Вот сериализаторы:
# 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
Метод get используется для получения данных с сервера. Например, список элементов, также обычно списки можно фильтровать по определенному критерию, для этого достаточно метода GET, просто передайте параметры в query-params, например так
example.com/elements?category=random
query-params также можно использовать для сортировки и пагинации.
POST
Чаще всего метод post используется, когда вам нужно отправить определенные данные на сервер в теле запроса формы (если вы используете шаблоны django), создать запись в базе данных и тому подобное.
Поэтому, чтобы решить для себя, какой запрос отправить на сервер, просто задайте себе вопрос: "Что сейчас может сделать клиент?" - Если вы получаете список/один элемент, то вам нужно отправить GET, если клиенту нужно отправить что-то вам на сервер, то POST.
И, наконец, есть такое правило, если вы не знаете, какой запрос отправить, когда вы сомневаетесь, то нужно отправить POST-запрос, например, в случае выхода из системы.