Как настроить параметры 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
.