Search code examples
djangodjango-modelsserializationdjango-rest-framework

Django Rest Framework's Nested Serializers POST Request ForeignKey Error


I'm working on a blood analysis lab availability check project, I'm using DRF(Django Rest Framework) to build the API.

I'm facing Not Null Constraints problems whenever i try to post data that contains a OneToOne relationship(ForeignKey).

here are the concerned models in my models.py file:

class Exam(models.Model):
    name = models.CharField(max_length=100,unique=True,blank=False)
    abbrv = models.CharField(max_length=100,unique=True,blank=False,null=False)
    price = models.IntegerField(blank=False,null=False)
    description = models.TextField(max_length=1000,blank=False,null=False)
    available = models.BooleanField(blank=False,null=False,default=True)
    _type = models.CharField(max_length=64,blank=False,null=False)
    created_at = models.DateTimeField(auto_now_add=True)

    def __str__(self):
        return self.abbrv




class Order(models.Model):
    patient = models.CharField(max_length=100,blank=False)
    code = models.CharField(max_length=100,unique=True,blank=False,null=False)
    total = models.IntegerField(blank=False,null=False)
    done = models.BooleanField(blank=False,null=False,default=True)
    exams =  models.ForeignKey(Exam, on_delete=models.CASCADE,related_name='ordered_exams')
    ordered_at = models.DateTimeField(auto_now_add=True)

and here are the concerned serializers in my serializers.pyfile:

class ExamSerializer(serializers.ModelSerializer):
    class Meta:
        model = Exam
        fields = '__all__'



class OrderSerializer(serializers.ModelSerializer):
    exams = ExamSerializer(many=0,read_only=1)
    
    class Meta:
        model = Order
        fields = '__all__'

and here are my concerned views in my view.py file:

class OrdersView(APIView):
    def get(self, request):
        order = Order.objects.all()
        serializer = OrderSerializer(order, many=True)
        return Response(serializer.data)

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

and here is my available exams that are returned from a GET request:

[
  {
    "id": 1,
    "name": "fns",
    "abbrv": "fns",
    "price": 500,
    "description": "Formule et Numerisation Sanguine",
    "available": true,
    "_type": "hemo",
    "created_at": "2023-04-26T14:16:13.301701Z"
  }
]

and whenever i send a POST request with this JSON object:

{
  "patient":"kimanxo",
  "code":313,
  "total":9500,
  "exams":1
}

i get this error : django.db.utils.IntegrityError: NOT NULL constraint failed: api_order.exams_id.

i tried to set a default value to the order.exams field,it worked, but all orders were placed under the same exam(the default value), and i couldn't override that by specifying the exams id value on the JSON object of each POST request.


Solution

  • edit here are the concerned OrderSerializer in your serializers.pyfile:

    class OrderSerializer(serializers.ModelSerializer): # exams = ExamSerializer(many=0,read_only=1) just remove this line

    class Meta:
        model = Order
        fields = '__all__'
    
    # Use this to_representation to show the exam detail
    def to_representation(self, instance):
        data = super().to_representation(instance)
        data['exams'] = ExamSerializer(instance.exams).data
        return data