devmrh
devmrh

Reputation: 1211

django-rest save array of data to db

hi im trying to save a form data into db. i provided print of requset.data for you as you see requirement have two items.

i want to save each item in database i used for loop to save each item of list but the loop will save each character of item like h-e-l,... in table row... where is my mistake ... thanks

also print of request.data.get('requirement') will retun second item

this is print of request.data in sever:

<QueryDict: {'requirement': ['hello', 'bye'], 'audience': ['adasd'], 'achievement': ['asdasd'], 'section': ['410101010'], 'title': ['asdasd'], 'mini_description': ['asdad'], 'full_description': ['asdasd'], 'video_length': ['10101'], 'video_level': ['P'], 'price': [''], 'free': ['true'], 'image': [<InMemoryUploadedFile: p.gif (image/gif)>]}>

view:

class StoreCreateAPIView(generics.CreateAPIView):
    parser_classes = (MultiPartParser, FormParser)
    permission_classes = [IsAuthenticated]

    def perform_create(self, serializer):
        serializer.save(author=self.request.user)

    def post(self, request, *args, **kwargs):
        if request.method == 'POST':
            print(request.data)
            file_serial = ProductSerializer(data=request.data, context={"request": request})
            if file_serial.is_valid():
                file_serial.save(author_id=request.user.id)
                requirement = request.data['requirement']
                audience = request.data.get('audience')
                achievement = request.data.get('achievement')
                sections = request.data.get('section')

                print(request.data['requirement'])
                pid = file_serial.data.get('product_id')
                for item in requirement :
                    req = ProductRequiredItems(
                        item = item,
                        product_id = pid
                    )
                    req.save()

Upvotes: 1

Views: 974

Answers (1)

an0o0nym
an0o0nym

Reputation: 1516

First of all, overriding CreateAPIView's post method in your code makes your custom perform_create method useless, unless you explicitly call it from within your customized post method. Otherwise it will never be called.

also print of request.data.get('requirement') will retun second item

It does return the last item as per Django docs for QueryDict.__getitem__(key).

i want to save each item in database i used for loop to save each item of list but the loop will save each character of item like h-e-l,...

This is because of the above functionality of QueryDict. When you do:

requirement = request.data['requirement']
# requirement = request.__getitem__('requirement')

it will call QueryDict.__getitem__(key) method and thus return only the last item (which is string in you example).

Answer:

You can simply override CreateAPIView's create method, and let your serializer handle all the rest.

# views.py
from django.shortcuts import render
from rest_framework import generics, status
from rest_framework.response import Response
from .models import MyObj
from .serializers import MyObjSerializer

class MyObjView(generics.CreateAPIView):
    serializer_class = MyObjSerializer
    queryset = MyObj.objects.all()

    def create(self, request, *args, **kwargs):
        # The QueryDicts at request.POST and request.GET will be immutable 
        # when accessed in a normal request/response cycle. 
        # To get a mutable version you need to use QueryDict.copy().
        req_data = request.data.copy()
        requirements = req_data.pop('requirement')
        serializers_data = []
        for requirement in requirements:
            req_data ['requirement'] = requirement
            serializer = self.get_serializer(data=req_data)
            serializer.is_valid(raise_exception=True)
            self.perform_create(serializer)
            serializers_data.append(serializer.data)
        return Response(serializers_data, status=status.HTTP_201_CREATED)

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

class MyObjSerializer(serializers.ModelSerializer):
    class Meta:
        model = MyObj
        fields = '__all__'

Have a look at DRF CreateModelMixin. It defines create & perform_create methods that are used used in CreateAPIView upon executing POST request. I just altered them slightly to handle your specific case.

Hope it helps.

Upvotes: 3

Related Questions