Как настроить параметры ID в django_rest_framework APIView

Моя цель - определить поведение, которое позволит мне ввести идентификатор в URL.

В настоящее время я могу отправлять запросы GET, PUT и PATCH на URL 'localhost:8000/api/?id=#', где хэш представляет собой любой идентификатор объекта.

Я хотел бы обновить свой код, чтобы понять, что если я отправляю запрос GET/PUT/PATCH на 'localhost:8000/api/2', что я ищу объект с id=2

my models.py

class player(models.Model):
    first_name = models.CharField(max_length=50)
    last_name = models.CharField(max_length=50)
    team = models.CharField(max_length=50)
    position = models.CharField(max_length=50)
    number = models.IntegerField()

    def __str__(self):
        return "{}, {}".format(self.first_name, self.last_name)

my serializer.py

class playerSerializer(serializers.ModelSerializer):

    class Meta:
        model = player
        fields = ['id', 'first_name', 'last_name', 'team', 'position', 'number']

my views.py

from django.shortcuts import render
from django.http import HttpResponse, response
from django.shortcuts import get_object_or_404
from rest_framework import serializers
from rest_framework. serializers import Serializer
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework import status
from main.models import player
from .serializers import playerSerializer
import json


class playerList(APIView):

    serializer_class = playerSerializer
    throttle_scope = "main_app"

    def get_queryset(self, *args, **kwargs):
        players = player.objects.all()
        return players

    def get(self, request, *args, **kwargs):     
        try:
            id = request.query_params["id"]
            if id != None:
                player_object = player.objects.get(id=id)
                serializer = playerSerializer(player_object)
        except:
            players = self.get_queryset()
            serializer = playerSerializer(players, many=True)

        return Response(serializer.data)

    def post(self, request):
        player_data = request.data
        new_player = player.objects.create(
            first_name=player_data['first_name'],
            last_name=player_data['last_name'],
            team=player_data['team'],
            position=player_data['position'],
            number=player_data['number']
        )
        new_player.save()

        serializer = playerSerializer(new_player)
        return Response(serializer.data)

    def put(self, request, *args, **kwargs):
        id = request.query_params["id"]
        player_object = player.objects.get(id=id)

        data = request.data

        player_object.first_name = data["first_name"]
        player_object.last_name = data["last_name"]
        player_object.team = data["team"]
        player_object.position = data["position"]
        player_object.number = data["number"]

        player_object.save()

        serializer = playerSerializer(player_object)
        return Response(serializer.data)
    
    def patch(self, request, *args, **kwargs):
        id = request.query_params["id"]
        player_object = player.objects.get(id=id)

        data = request.data

        player_object.first_name = data.get('first_name', player_object.first_name)
        player_object.last_name = data.get('last_name', player_object.last_name)
        player_object.team = data.get('team', player_object.team)
        player_object.position = data.get('position', player_object.position)
        player_object.number = data.get('number', player_object.number)

        player_object.save()
        serializer = playerSerializer(player_object)
        return Response(serializer.data)

Я застрял на этой проблеме в течение нескольких дней... любое руководство было бы очень признательно.

Спасибо, Остин H

views.py


class playerList(APIView):

    serializer_class = playerSerializer
    throttle_scope = "main_app"
    
    def get_queryset(self, *args, **kwargs):
        players = player.objects.all()
        return players

    def get(self, request, *args, **kwargs):     
        try:
            # id = request.query_params["id"]
            id = self.kwargs["id"]
              if id != None:
                player_object = player.objects.get(id=id)
                serializer = playerSerializer(player_object)
        except:
            players = self.get_queryset()
            serializer = playerSerializer(players, many=True)

        return Response(serializer.data)

    def post(self, request):
        player_data = request.data
        new_player = player.objects.create(
            first_name=player_data['first_name'],
            last_name=player_data['last_name'],
            team=player_data['team'],
            position=player_data['position'],
            number=player_data['number']
        )
        new_player.save()

        serializer = playerSerializer(new_player)
        return Response(serializer.data)

    def put(self, request, *args, **kwargs):
        #id = request.query_params["id"]
        id = self.kwargs["id"]
        player_object = player.objects.get(id=id)

        data = request.data

        player_object.first_name = data["first_name"]
        player_object.last_name = data["last_name"]
        player_object.team = data["team"]
        player_object.position = data["position"]
        player_object.number = data["number"]

        player_object.save()

        serializer = playerSerializer(player_object)
        return Response(serializer.data)
    
    def patch(self, request, *args, **kwargs):
        #id = request.query_params["id"]
        id = self.kwargs["id"]
        player_object = player.objects.get(id=id)

        data = request.data

        player_object.first_name = data.get('first_name', player_object.first_name)
        player_object.last_name = data.get('last_name', player_object.last_name)
        player_object.team = data.get('team', player_object.team)
        player_object.position = data.get('position', player_object.position)
        player_object.number = data.get('number', player_object.number)

        player_object.save()
        serializer = playerSerializer(player_object)
        return Response(serializer.data)

urls.py

urlpatterns = [
    url('players/<int:id>/', playerList.as_view()),
]

Я бы очень советовал использовать DRF's viewsets, так как он покроет большинство вещей, которые вам нужны здесь с небольшим количеством кода. Но если вы хотите поиграть с этим самостоятельно с вашим текущим представлением:

Сначала вы должны определить другой url, который принимает id игрока, сохраняя старый url для сохранения текущего поведения, которое вы хотите:

urlpatterns = [
    url('players/<int:pk>', playerList.as_view()),
    url('players', playerList.as_view()),
]

players/<int:pk> будет поддерживать урлы типа players/1 и передавать 1 в качестве аргумента ключевого слова pk в представлении.

Затем вы можете изменить свой вид на что-то вроде этого:

from django.shortcuts import get_object_or_404


class playerList(APIView):
    ...

    def get_object(self, id)
        return get_object_or_404(self.get_queryset(), id=id)

    def get(self, request, pk=None, *args, **kwargs):     
        id = pk or request.query_params.get('id')
        if id:
            serializer = playerSerializer(self.get_object(id))
        else:
            serializer = playerSerializer(self.get_queryset(), many=True)

        return Response(serializer.data)

    def post(self, request, *args, **kwargs):
        ...

    def put(self, request, pk=None, *args, **kwargs):
        player_object = self.get_object(pk or request.query_params.get('id'))
        ...
    
    def patch(self, request, pk=None, *args, **kwargs):
        player_object = self.get_object(pk or request.query_params.get('id'))
        ...
id = pk or request.query_params.get('id')

Это означает, что если pk не был передан (т.е. не был использован url players/1), то представление просто будет действовать по старинке, получая id из request.query_params. Вот почему также установлен параметр pk=None, на случай, если мы получим id из параметров запроса. Также обратите внимание, что post должен также захватывать args и kwargs.

Вернуться на верх