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
.