RESTful API от представлений на основе функций до представлений на основе классов django rest framework - PullRequest
0 голосов
/ 09 октября 2018

Я следовал этому уроку здесь: https://realpython.com/test-driven-development-of-a-django-restful-api/

Я все настроил, и конечные точки API работают должным образом: Когда я вызываю: localhost / api / v1 / puppies / return:

{
    "name": "Bridgett",
    "age": 3,
    "breed": "Boxer",
    "color": "White",
    "created_at": "2018-10-03T17:28:21.333893Z",
    "updated_at": "2018-10-03T17:34:13.899385Z"
},
{
    "name": "Mia",
    "age": 3,
    "breed": "Mix",
    "color": "Black",
    "created_at": "2018-10-09T16:08:59.775685Z",
    "updated_at": "2018-10-09T16:08:59.775685Z"
}

Также работает и основная проблема, которая является представлением «Подробности» ... Если я позвоню: localhost / api / v1 / puppies / 2 возвращает:

{
    "name": "Bridgett",
    "age": 3,
    "breed": "Boxer",
    "color": "White",
    "created_at": "2018-10-03T17:28:21.333893Z",
    "updated_at": "2018-10-03T17:34:13.899385Z"
}

Что здоровои все мои положенные пост удаления также работает вот код:

models.py:

# models.py
from django.db import models


class Puppy(models.Model):
    """
    Puppy Model
    Defines the attributes of a puppy
    """
    name = models.CharField(max_length=255)
    age = models.IntegerField()
    breed = models.CharField(max_length=255)
    color = models.CharField(max_length=255)
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)

    def __str__(self):
        return self.name

    def get_breed(self):
        return self.name + ' belongs to ' + self.breed + ' breed.'

    def __repr__(self):
        return self.name + ' is added.'

serializers.py

# serializers.py
from rest_framework import serializers
from .models import Puppy


class PuppySerializer(serializers.ModelSerializer):
    class Meta:
        model = Puppy
        fields = ('name', 'age', 'breed', 'color', 'created_at', 'updated_at')

views.py

from django.shortcuts import render
from rest_framework.decorators import api_view
# from rest_framework.decorators import APIView
from rest_framework.response import Response
from rest_framework import status
from django.views.generic import TemplateView
from .models import Puppy
from .serializers import PuppySerializer

@api_view(['GET', 'DELETE', 'PUT'])
def get_delete_update_puppy(request, pk):
    try:
        puppy = Puppy.objects.get(pk=pk)
    except Puppy.DoesNotExist:
        return Response(status=status.HTTP_404_NOT_FOUND)

    # get details of a single puppy
    if request.method == 'GET':
        serializer = PuppySerializer(puppy)
        return Response(serializer.data)
    # update details of a single puppy
    if request.method == 'PUT':
        serializer = PuppySerializer(puppy, data=request.data)
        if serializer.is_valid():
            serializer.save()
            return Response(serializer.data, status=status.HTTP_204_NO_CONTENT)
        return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
    # delete a single puppy
    if request.method == 'DELETE':
        puppy.delete()
        return Response(status=status.HTTP_204_NO_CONTENT)


@api_view(['GET', 'POST'])
def get_post_puppies(request):
    # get all puppies
    if request.method == 'GET':
        puppies = Puppy.objects.all()
        serializer = PuppySerializer(puppies, many=True)
        return Response(serializer.data)

    # insert a new record for a puppy
    if request.method == 'POST':
        data = {
            'name': request.data.get('name'),
            'age': int(request.data.get('age')),
            'breed': request.data.get('breed'),
            'color': request.data.get('color')
        }
        serializer = PuppySerializer(data=data)
        if serializer.is_valid():
            serializer.save()
            return Response(serializer.data, status=status.HTTP_201_CREATED)
        return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)

urls.py

from django.conf.urls import url
from . import views


urlpatterns = [
    url(
        r'^api/v1/puppies/(?P<pk>[0-9]+)$',
        # views.PuppyDetail.as_view(),
        views.get_delete_update_puppy,
        name='get_delete_update_puppy'
    ),
    url(
        r'^api/v1/puppies/$',
        # views.PuppyList.as_view(),
        views.get_post_puppies,
        name='get_post_puppies'
    )
]

Все это работает, как и ожидалось, однако у меня возникает проблема, когда я заменяю код в views.py и urls.py, как при использовании классаоснованные представления Я ничего не возвращаю в вызове API подробного представления: localhost / api / v1 / puppies / 2 возвращает:

{
    "name": "",
    "age": null,
    "breed": "",
    "color": ""
}

Обновленный код такой:

views.py

from django.shortcuts import render
# from rest_framework.decorators import api_view
from rest_framework.decorators import APIView
from rest_framework.response import Response
from rest_framework import status
from django.views.generic import TemplateView
from .models import Puppy
from .serializers import PuppySerializer


class PuppyDetail(APIView):
    """
    Get, update, or delete a single puppy instance
    """
    def get_object(self, pk):
        try:
            puppy = Puppy.objects.get(pk=pk)
        except Puppy.DoesNotExist:
            return Response(status=status.HTTP_404_NOT_FOUND)

    def get(self, request, pk):
        # get details of a single puppy
        puppy = self.get_object(pk)
        serializer = PuppySerializer(puppy)
        return Response(serializer.data)

    def put(self, request, pk):
        # update details of a single puppy
        puppy = self.get_object(pk)
        serializer = PuppySerializer(puppy, data=request.data)
        if serializer.is_valid():
            serializer.save()
            return Response(serializer.data, status=status.HTTP_204_NO_CONTENT)
        return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)

    def delete(self, request, pk):
        puppy = self.get_object(pk)
        puppy.delete()
        return Response(status=status.HTTP_204_NO_CONTENT)


class PuppyList(APIView):
    """
    List all puppies, or create a new puppy
    """
    def get(self, request):
        puppies = Puppy.objects.all()
        serializer = PuppySerializer(puppies, many=True)
        return Response(serializer.data)

    def post(self, request):
        serializer = PuppySerializer(data=request.data)
        if serializer.is_valid():
            serializer.save()
            return Response(serializer.data, status=status.HTTP_201_CREATED)
        return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)

urls.py

from django.conf.urls import url
from . import views


urlpatterns = [
    url(
        r'^api/v1/puppies/(?P<pk>[0-9]+)$',
        views.PuppyDetail.as_view(),
        # views.get_delete_update_puppy,
        # name='get_delete_update_puppy'
    ),
    url(
        r'^api/v1/puppies/$',
        views.PuppyList.as_view(),
        # views.get_post_puppies,
        # name='get_post_puppies'
    )
]

Мой вопрос заключается в том, что такое разъединение, что мои вызовы API не работают, когда я реализую представления на основе классов?

После отладки с отпечатками я понял, что не добавляю возврат в get_object:

def get_object(self, pk):
    try:
        puppy = Puppy.objects.get(pk=pk)
        return(puppy)  # This needed to be added.
    except Puppy.DoesNotExist:
        return Response(status=status.HTTP_404_NOT_FOUND)

Я пропускал возврат объекта для отправки в вызов функции.Спасибо

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...