Search code examples
pythondjangodjango-rest-frameworkdjango-viewsdjango-serializer

Can't validate form with a many=true field in Django-rest


I am trying to use Django-rest as an api for a front end in astro, the think is I am finding a problem when doing my post:

{'items': [ErrorDetail(string='This field is required.', code='required')]}

My code is the next one:

views.py

from django.shortcuts import render

from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework import status
from .models import Ticket, Item
from .serializers import TicketSerializer, ItemSerializer
import json
# Create your views here.

class TicketView(APIView):
    def post(self, request, format=None):

        items = request.data.pop('items')[0]
        # Items are given as a string with the json format. We need to parse it.
        items = json.loads(items)[0]
        # Add the items to the request data
        data = request.data
        data['items'] = items
        
        data.pop('itemName0')
        data.pop('itemPrice0')
        data.pop('itemCount0')
        print(data)
        serializer = TicketSerializer(data=data)
        
        if serializer.is_valid():
            serializer.save()
            return Response(serializer.data, status=status.HTTP_201_CREATED)
        print(serializer.errors)
        return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)

Serializers

from .models import Ticket, Item
from rest_framework import serializers

class ItemSerializer(serializers.ModelSerializer):
    class Meta:
        model = Item
        fields = ('name', 'price', 'count')
class TicketSerializer(serializers.ModelSerializer):
    items = ItemSerializer(many=True)

    class Meta:
        model = Ticket
        fields = ('img', 'subtotal', 'service', 'tax', 'etc', 'total', 'items')

    def create(self, validated_data):
        items_data = validated_data.pop('items')
        ticket = Ticket.objects.create(**validated_data)
        for item_data in items_data:
            Item.objects.create(ticket=ticket, **item_data)
        return ticket


Output of printing the request.data after modifications in the view: <QueryDict: {'subtotal': ['12'], 'service': ['12'], 'tax': ['12'], 'etc': ['12'], 'total': ['120'], 'img': [<InMemoryUploadedFile: photo_2024-01-17 23.39.53.jpeg (image/jpeg)>, <InMemoryUploadedFile: photo_2024-01-17 23.39.53.jpeg (image/jpeg)>], 'items': [{'name': 'mei', 'count': '012', 'price': '012'}]}>

What could be happening? Because items is in the querydict and I think that in the right format. If not how can I know what is the right format for each type of field? Including the many=true fields.

I have tried living the items as they are received, changing it or even changing the is_valid, but I don't have enough knowledge to create my own version of is_valid.


Solution

  • Here You may not be passing properly item data Here is Example of item data passing.

    because you are creating multiple items items = ItemSerializer(many=True)

    You Have to Pass Data in Items according to this Format below

    {
    ...
    
    "items":[
             {"name":"a","price":100,"count":15}, 
             {"name":"a","price":100,"count":15},
             {"name":"a","price":100,"count":15}
            ]
    }