Home > OS >  How to configure ID parameters in django_rest_framework APIView
How to configure ID parameters in django_rest_framework APIView

Time:09-22

My goal is to specify behavior that allows me to enter an ID into my URL.

Currently, I am able to send GET, PUT, and PATCH requests to the URL 'localhost:8000/api/players/?id=#' where the hash represents player id

I would like to update my code to understand that if I send a GET/PUT/PATCH request to 'localhost:8000/api/players/2' that I am looking for a player with 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)

my urls.py

urlpatterns = [
    url('players', playerList.as_view()),
]

I have been stuck on this problem for a few days... any guidance would be greatly appreciated.

Thanks, Austin H

CodePudding user response:

views.py


class playerList(APIView):

    serializer_class = playerSerializer
    throttle_scope = "main_app"
    

    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()),
]

CodePudding user response:

I would highly suggest using DRF's viewsets as it will cover most of the things that you need here with little code. But if you want to play around it yourself with your current view:

First you have to define another url that accepts the player id, while keeping the old url to preserve the current behavior your want:

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

players/<int:pk> will support urls like players/1 and pass 1 as a keyword argument pk in the view.

You can then change your view to something like this:

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')

This means that if pk was not passed (i.e. the url used was not players/1) then the view will just do the old behavior you have by getting the id from request.query_params. This is also why pk=None is set, in case we get the id from the query params. Also note that post needs to also capture args and kwargs.

  • Related