Serializer saves to db but returns 500 bad request

I am trying to create a serializer to get user input and insert it in a patient record, to do this i have several models connected using foreignkey but when i send the data using postman the data gets saved in the dp but the api responds with a 500 bad request !!!

console

Validated data before pop:  {'ticket': 2, 'pressure': '125/75', 'diabetes': 123}
Ticket value after pop:  2
User's convoy:  Test 2
Appointment found:
Patient Test
Validated data before creating Detection:  {'pressure': '125/75', 'diabetes': 123, 'ticket': <Appointment: Patient Test>}
Detection created:  Patient Test
2 125/75 123
Internal Server Error: /early/api/detection/
Traceback (most recent call last):
  File "/usr/local/lib/python3.9/site-packages/django/core/handlers/exception.py", line 55, in inner       
    response = get_response(request)
  File "/usr/local/lib/python3.9/site-packages/django/core/handlers/base.py", line 197, in _get_response   
    response = wrapped_callback(request, *callback_args, **callback_kwargs)
  File "/usr/local/lib/python3.9/site-packages/django/views/decorators/csrf.py", line 56, in wrapper_view  
    return view_func(*args, **kwargs)
  File "/usr/local/lib/python3.9/site-packages/django/views/generic/base.py", line 104, in view
    return self.dispatch(request, *args, **kwargs)
  File "/usr/local/lib/python3.9/site-packages/rest_framework/views.py", line 509, in dispatch
    response = self.handle_exception(exc)
  File "/usr/local/lib/python3.9/site-packages/rest_framework/views.py", line 469, in handle_exception     
    self.raise_uncaught_exception(exc)
  File "/usr/local/lib/python3.9/site-packages/rest_framework/views.py", line 480, in raise_uncaught_exception
    raise exc
  File "/usr/local/lib/python3.9/site-packages/rest_framework/views.py", line 506, in dispatch
    response = handler(request, *args, **kwargs)
  File "/app/earlyDetection/views.py", line 16, in post
    return Response(serializer.data, status=status.HTTP_201_CREATED)
  File "/usr/local/lib/python3.9/site-packages/rest_framework/serializers.py", line 555, in data
    ret = super().data
  File "/usr/local/lib/python3.9/site-packages/rest_framework/serializers.py", line 253, in data
    self._data = self.to_representation(self.instance)
  File "/usr/local/lib/python3.9/site-packages/rest_framework/serializers.py", line 522, in to_representation
    ret[field.field_name] = field.to_representation(attribute)
  File "/usr/local/lib/python3.9/site-packages/rest_framework/fields.py", line 915, in to_representation   
    return int(value)
TypeError: int() argument must be a string, a bytes-like object or a number, not 'Appointment'
[16/Nov/2023 15:18:26] "POST /early/api/detection/ HTTP/1.1" 500 102016

models.py

class Detection(models.Model):
    # Unique identifier for each appointment
    id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False, max_length=36)
    # Patients's number
    ticket = models.ForeignKey(Appointment, on_delete=models.CASCADE)
    # Blood pressure
    pressure = models.CharField(max_length=10)
    # Diabeties reading
    diabetes = models.IntegerField()
    # Accumulated diabeties reading
    acc_Diabetes = models.IntegerField(null= True, blank= True)
    # Extra Fields
    field = models.ForeignKey(Field, on_delete=models.CASCADE, null= True, blank= True)
    # Date of detection
    createdAt = models.DateTimeField(auto_now_add=True)

    def __str__(self):
        return f'{self.ticket.patient.first_name} {self.ticket.patient.last_name}'

class Appointment(models.Model):
    # Unique identifier for each appointment
    id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False, max_length=36)
    # Patient name
    patient = models.ForeignKey(Patient, on_delete=models.CASCADE)
    # Convoy name
    convoy = models.ForeignKey(Convoy, on_delete=models.CASCADE)
    # Field to store patient queue number
    queue = models.PositiveIntegerField(default=0) 
    # Date and time when the appointment was created
    created = models.DateTimeField(auto_now_add=True)

    def __str__(self):
        return f'{self.patient.first_name} {self.patient.last_name}'

    def save(self, *args, **kwargs):
        if not self.queue:
            # Get the latest appointment for this convoy to determine the next queue number
            latest_appointment = Appointment.objects.filter(convoy=self.convoy).order_by('-queue').first()
            new_queue = 1 if latest_appointment is None else latest_appointment.queue + 1
            self.queue = new_queue
            
        super().save(*args, **kwargs)

serializer.py

from rest_framework import serializers
from .models import Detection, Appointment

class DetectionSerializer(serializers.ModelSerializer):
    ticket = serializers.IntegerField()

    class Meta:
        model = Detection
        fields = ['ticket', 'pressure', 'diabetes', 'acc_Diabetes', 'field']

    def create(self, validated_data):
        print("Validated data before pop: ", validated_data)
        ticket = validated_data.pop('ticket')
        print("Ticket value after pop: ", ticket)
        user = self.context['request'].user  # Get the logged-in user
        print("User's convoy: ", user.convoy)
        try:
            # Filter appointments based on the user's convoy
            appointment = Appointment.objects.get(convoy=user.convoy, queue=ticket)
            print("Appointment found: ", appointment)
        except Appointment.DoesNotExist:
            raise serializers.ValidationError("Appointment does not exist")

        validated_data['ticket'] = appointment
        print("Validated data before creating Detection: ", validated_data)

        detection = Detection.objects.create(**validated_data)
        print("Detection created: ", detection)

        print(detection.ticket.queue, detection.pressure, detection.diabetes)

        return detection

views.py

class DetectionCreateView(APIView):
    def get_serializer_context(self):
        return {'request': self.request}

    def post(self, request, *args, **kwargs):
        serializer = DetectionSerializer(data=request.data, context=self.get_serializer_context())
        
        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.urls import path, include
from . import views
# from .views import UserViewSet

app_name= "early"

urlpatterns = [
    path('api/detection/', views.DetectionCreateView.as_view(), name='detection'),
]

Postman request


In DetectionSerializer wrap your whole code within try except block like

class DetectionSerializer(serializers.ModelSerializer):
    .....

    def create(self, validated_data):
        try:
            # Your code here
        except Exception as e:
            print("-----------Exception-------", e)

check what print statement prints in your console.

my new serilaizer.py

class DetectionSerializer(serializers.ModelSerializer):
    ticket = serializers.IntegerField()

    class Meta:
        model = Detection
        fields = ['ticket', 'pressure', 'diabetes', 'acc_Diabetes', 'field']

    def create(self, validated_data):
        try:
            print("Validated data before pop: ", validated_data)
            ticket = validated_data.pop('ticket')
            print("Ticket value after pop: ", ticket)
            user = self.context['request'].user  # Get the logged-in user
            print("User's convoy: ", user.convoy)
            try:
                # Filter appointments based on the user's convoy
                appointment = Appointment.objects.get(convoy=user.convoy, queue=ticket)
                print("Appointment found: ", appointment)
            except Appointment.DoesNotExist:
                raise serializers.ValidationError("Appointment does not exist")

            validated_data['ticket'] = appointment
            print("Validated data before creating Detection: ", validated_data)

            detection = Detection.objects.create(**validated_data)
            print("Detection created: ", detection)

            print(detection.ticket.queue, detection.pressure, detection.diabetes)

            return detection
        except Exception as e:
            print("-----------Exception-------", e)

console

Validated data before pop:  {'ticket': 2, 'pressure': '125/75', 'diabetes': 123}
Ticket value after pop:  2
User's convoy:  Test 2
Appointment found:
Patient Test
Validated data before creating Detection:  {'pressure': '125/75', 'diabetes': 123, 'ticket': <Appointment: Patient Test>}
Detection created:  Patient Test
2 125/75 123
Internal Server Error: /early/api/detection/
Traceback (most recent call last):
  File "/usr/local/lib/python3.9/site-packages/django/core/handlers/exception.py", line 55, in inner       
    response = get_response(request)
  File "/usr/local/lib/python3.9/site-packages/django/core/handlers/base.py", line 197, in _get_response   
    response = wrapped_callback(request, *callback_args, **callback_kwargs)
  File "/usr/local/lib/python3.9/site-packages/django/views/decorators/csrf.py", line 56, in wrapper_view  
    return view_func(*args, **kwargs)
  File "/usr/local/lib/python3.9/site-packages/django/views/generic/base.py", line 104, in view
    return self.dispatch(request, *args, **kwargs)
  File "/usr/local/lib/python3.9/site-packages/rest_framework/views.py", line 509, in dispatch
    response = self.handle_exception(exc)
  File "/usr/local/lib/python3.9/site-packages/rest_framework/views.py", line 469, in handle_exception     
    self.raise_uncaught_exception(exc)
  File "/usr/local/lib/python3.9/site-packages/rest_framework/views.py", line 480, in raise_uncaught_exception
    raise exc
  File "/usr/local/lib/python3.9/site-packages/rest_framework/views.py", line 506, in dispatch
    response = handler(request, *args, **kwargs)
  File "/app/earlyDetection/views.py", line 16, in post
    return Response(serializer.data, status=status.HTTP_201_CREATED)
  File "/usr/local/lib/python3.9/site-packages/rest_framework/serializers.py", line 555, in data
    ret = super().data
  File "/usr/local/lib/python3.9/site-packages/rest_framework/serializers.py", line 253, in data
    self._data = self.to_representation(self.instance)
  File "/usr/local/lib/python3.9/site-packages/rest_framework/serializers.py", line 522, in to_representation
    ret[field.field_name] = field.to_representation(attribute)
  File "/usr/local/lib/python3.9/site-packages/rest_framework/fields.py", line 915, in to_representation   
    return int(value)
TypeError: int() argument must be a string, a bytes-like object or a number, not 'Appointment'
[16/Nov/2023 15:31:49] "POST /early/api/detection/ HTTP/1.1" 500 102016

i believe the problem is that my class detectin is returning
def str(self):
return f’{self.ticket.patient.first_name} {self.ticket.patient.last_name}’

Validated data before creating Detection: {‘pressure’: ‘125/75’, ‘diabetes’: 123, ‘ticket’: <Appointment: Patient Test>}
but the ticket expects a number but i don’t know how to fix this issue !!

One more thing I’ve seen just now, In your serializer

ticket = serializers.IntegerField()

and in your models

ticket = models.ForeignKey(Appointment, on_delete=models.CASCADE)

Problem is because of this, You don’t need to give ticket a IntegerField it is a ForeignKey. So even if you pass the id of ticket via postman, it will save it.

so what should i change the ticket to ?

do i completely remove this line

ticket = serializers.IntegerField()

yes, you can it is not really needed.

i removed it now it is treating the ticket value as primary key which is not, the ticket value refers to the queue inside the Appointment class

{
    "ticket": [
        "Invalid pk \"2\" - object does not exist."
    ]
}

The ticket in your models is a ForeignKey and it will only accept the values of Appointment objects that are created. in your case it is stating that pk with 2 is not created for Appointment table.
If you ticket have some other functionality then you should work around it and elaborate it more.

i need to link the detection with ticket to know the patient and add this data to him.
each patient gets a queue number from appointment this number exists in appointmnet.queue can i link directly with queue and not the uuid

class Appointment(models.Model):
    # Unique identifier for each appointment
    id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False, max_length=36)
    # Patient name
    patient = models.ForeignKey(Patient, on_delete=models.CASCADE)
    # Convoy name
    convoy = models.ForeignKey(Convoy, on_delete=models.CASCADE)
    # Field to store patient queue number
    queue = models.PositiveIntegerField(default=0) 
    # Date and time when the appointment was created
    created = models.DateTimeField(auto_now_add=True)

    def __str__(self):
        return f'{self.patient.first_name} {self.patient.last_name}'

    def save(self, *args, **kwargs):
        if not self.queue:
            # Get the latest appointment for this convoy to determine the next queue number
            latest_appointment = Appointment.objects.filter(convoy=self.convoy).order_by('-queue').first()
            new_queue = 1 if latest_appointment is None else latest_appointment.queue + 1
            self.queue = new_queue
            
        super().save(*args, **kwargs)

when i check the db the record is added the problem is with the response returned from the api !!!

I got it to work by doing the following:
serializer.py

class DetectionSerializer(serializers.ModelSerializer):
    ticket = serializers.CharField()  # Using CharField for queue instead of IntegerField

    class Meta:
        model = Detection
        fields = ['ticket', 'pressure', 'diabetes', 'acc_Diabetes']

    def create(self, validated_data):
        queue = validated_data.pop('ticket')
        user = self.context['request'].user

        try:
            appointment = Appointment.objects.get(convoy=user.convoy, queue=int(queue))
        except (Appointment.DoesNotExist, ValueError):
            raise serializers.ValidationError("Appointment does not exist")

        detection = Detection.objects.create(ticket=appointment, **validated_data)

        return detection

views.py

class DetectionCreateView(APIView):
    def get_serializer_context(self):
        return {'request': self.request}

    def post(self, request, *args, **kwargs):
        serializer = DetectionSerializer(data=request.data, context=self.get_serializer_context())
        
        if serializer.is_valid():
            serializer.save()
            print(f'response: {serializer.data}')
            return Response(serializer.data, status=status.HTTP_201_CREATED)
        
        return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)