1

I have a Django project that is using Django Rest Framework. For some reason, when I go to one of my endpoints (to make a PATCH/PUT request), I am not seeing any of the form fields in the browsable API. Here is the code for the resource:

models.py

from django.db import models


class Patient(models.Model):
    first_name = models.CharField(max_length=100)
    last_name = models.CharField(max_length=100)
    diagnosis = models.CharField(max_length=200)
    primary_doctor = models.ForeignKey('Doctor', related_name='patients', on_delete=models.CASCADE, null=True)
    born_on = models.DateField()
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)

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

views.py

from rest_framework.views import APIView
from rest_framework.generics import RetrieveUpdateDestroyAPIView
from rest_framework.response import Response
from rest_framework import status
from django.shortcuts import get_object_or_404

from ..models.patient import Patient
from ..serializers import PatientSerializer


class Patients(APIView):
    def get(sef, request):
        patients = Patient.objects.all()[:10]
        serializer = PatientSerializer(patients, many=True)
        return Response(serializer.data)

    serializer_class = PatientSerializer

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

class PatientDetail(APIView):
    def get(self, request, pk):
        patient = get_object_or_404(Patient, pk=pk)
        serializer = PatientSerializer(patient)
        return Response(serializer.data)

    serializer_class = PatientSerializer

    def patch(self, request, pk):
        patient = get_object_or_404(Patient, pk=pk)
        serializer = PatientSerializer(patient, data=request.data['patient'])
        if serializer.is_valid():
            serializer.save()
            return Response(serializer.data, status=status.HTTP_202_ACCEPTED)
        else:
            return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)

    def delete(self, request, pk):
        patient = get_object_or_404(Patient, pk)
        patient.delete()
        return Response(status=status.HTTP_204_NO_CONTENT)

serializers.py

from rest_framework import serializers

from .models.patient import Patient


class PatientSerializer(serializers.ModelSerializer):
    class Meta:
        model = Patient
        fields = ('id', 'first_name', 'last_name', 'diagnosis', 'born_on', 'primary_doctor', 'created_at', 'updated_at')

urls.py

from django.urls import path
from .views.doctor_views import Doctors, DoctorDetail
from .views.patient_views import Patients, PatientDetail

urlpatterns = [
    path('doctors/', Doctors.as_view(), name='doctors'),
    path('doctors/<int:pk>/', DoctorDetail.as_view(), name='doctor_detail'),
    path('patients/', Patients.as_view(), name='patients'),
    path('patients/<int:pk>/', PatientDetail.as_view(), name='patient_detail'),
]

This is what the browser looks like when I go to '/patients/3'. There are no form fields to fill out, only a content area for JSON. When I go to POST at '/patients', the form fields appear and I can POST fine. Could anyone tell me why this might be happening?

ghood97
  • 161
  • 1
  • 12

1 Answers1

2

If you change PatientDetail's patch method to put, the form should appear and function properly at the url to update a patient. You can use them somewhat interchangeably with DRF, to my understanding (No difference between PUT and PATCH in Django REST Framework). The difference lies in whether the serializer fields are required or not.

Though, they are technically different things at a low level - patch being a real 'partial update' (Use of PUT vs PATCH methods in REST API real life scenarios).

In the put method, you also should change

serializer = PatientSerializer(patient, data=request.data['patient'])

to

serializer = PatientSerializer(data=request.data)

Then, the endpoints should behave as expected.

twrought
  • 636
  • 5
  • 9