ทำให้ InMemoryUploadedFile หลายไฟล์เป็นอนุกรมโดยใช้ ListField: Django REST Framework

ฉันจะซีเรียลไลซ์ InMemoryUploadedFile โดยใช้ serializers.ListField() ??


ข้อมูลโค้ด

#views.py
@api_view(['POST', 'GET'])
def create_post(request):
    if request.method == 'POST':
        altered_request_data = request.data.copy()
        in_memory_upload_files_list = [value for value in request.FILES.values()]
        altered_request_data['files'] = in_memory_upload_files_list
        serializer = PostSerializer(data=altered_request_data)
        serializer.is_valid(raise_exception=True)
        serializer.save()
        return Response(data=serializer.data, status=201)
    else:
        qs = Post.objects.all()
        serializer = PostSerializer(qs, many=True)
        return Response(serializer.data)

#serilizers.py
class PostSerializer(serializers.ModelSerializer):
    files = serializers.ListField(child=serializers.FileField(), write_only=True)

    class Meta:
        fields = '__all__'
        model = Post

การตอบสนองปัจจุบัน

{
    "files": {
        "0": [
            "The submitted data was not a file. Check the encoding type on the form."
        ]
    }
}

comment
ฉันคิดว่าคุณไม่ต้องการมัน เพราะคุณโทร save เพียงแค่ประมวลผลไฟล์ในการบันทึก แล้วทุกอย่างจะเรียบร้อย   -  person Brown Bear    schedule 25.04.2019
comment
การตอบสนองที่กำหนดเป็นข้อผิดพลาดในการตรวจสอบความถูกต้องและเกิดขึ้นก่อนที่จะเรียกใช้เมธอด save()   -  person JPG    schedule 25.04.2019


คำตอบ (2)


ปัญหาอยู่ในบรรทัดนี้

altered_request_data['files'] = in_memory_upload_files_list

ที่นี่ altered_request_data คือ QueryDict วัตถุ ดังนั้นหากเรากำหนดสิ่งใดให้กับวัตถุนั้นจะเรียก __setitem__() วิธีการ

In [6]: from django.http import QueryDict                                                                                                                                                                          

In [7]: qd = QueryDict('a=1&a=2&c=3',mutable=True)                                                                                                                                                                 

In [8]: qd                                                                                                                                                                                                         
Out[8]: <QueryDict: {'a': ['1', '2'], 'c': ['3']}>

In [9]: my_list = [i for i in range(10)]                                                                                                                                                                           

In [10]: my_list                                                                                                                                                                                                   
Out[10]: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

In [11]: qd['foo']=my_list                                                                                                                                                                                         

In [12]: qd                                                                                                                                                                                                        
Out[12]: <QueryDict: {'a': ['1', '2'], 'c': ['3'], 'foo': [[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]]}>

เห็นไหม? qd['foo'] กลายเป็น รายการ นั่นคือ สิ่งใดก็ตามที่กำหนดให้กับ QueryDict จะถูกจัดเก็บไว้ในวัตถุ list

แล้วมีทางแก้อะไรบ้าง??

QueryDict คลาสมีเมธอด QueryDict.setlist จะทำงาน

In [15]: qd__new                                                                                                                                                                                                   
Out[15]: 

In [16]: qd__new = QueryDict('a=1&a=2&c=3',mutable=True)                                                                                                                                                           

In [17]: qd__new                                                                                                                                                                                                   
Out[17]: <QueryDict: {'a': ['1', '2'], 'c': ['3']}>

In [18]: my_list                                                                                                                                                                                                   
Out[18]: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

In [19]: qd__new.setlist('foo_new',my_list)                                                                                                                                                                        

In [20]: qd__new                                                                                                                                                                                                   
Out[20]: <QueryDict: {'a': ['1', '2'], 'c': ['3'], 'foo_new': [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]}>

ข้อมูลโค้ด

มุมมอง.py

@api_view(['POST', 'GET'])
def create_post(request):
    if request.method == 'POST':
        altered_request_data = request.data.copy()
        in_memory_upload_files_list = [value for value in request.FILES.dict().values()]

        altered_request_data.setlist('files', in_memory_upload_files_list)

        serializer = PostSerializer(data=altered_request_data)
        serializer.is_valid(raise_exception=True)
        serializer.save()
        return Response(data=serializer.data, status=201)
    else:
        qs = Post.objects.all()
        serializer = PostSerializer(qs, many=True)
        return Response(serializer.data)
person JPG    schedule 25.04.2019

คุณควรใช้เมธอด getlist ของ FILES ที่จะให้รายการไฟล์แก่คุณ

in_memory_upload_files_list = request.FILES.getlist('<file field name>')
altered_request_data['files'] = in_memory_upload_files_list
serializer = PostSerializer(data=altered_request_data)

ที่นี่ <file field name> จะเป็นฟิลด์ชื่อไฟล์ที่คุณอัปโหลดไฟล์

https://docs.djangoproject.com/en/2.2/ref/request-response/#django.http.QueryDict.getlist

person Neeraj Kumar    schedule 25.04.2019
comment
ฉันกำลังอัปโหลดไฟล์ดังนี้ - ภาพหน้าจอ และฉันไม่สนใจที่จะระบุ ชื่อในวิธี getlist() เนื่องจากฉันกำลังอัปโหลดหลายไฟล์ - person JPG; 25.04.2019
comment
คุณกำลังใช้ไฟล์คีย์ เพียงแค่ใส่การแทนที่ไฟล์ใน ‹ชื่อฟิลด์ไฟล์› ในสแน็ปช็อตที่คุณพูดถึง file_1 นั้น file_2 หมายถึงบุรุษไปรษณีย์ที่อัพโหลดรูปภาพตามชื่อฟิลด์ของไฟล์ - person Neeraj Kumar; 25.04.2019
comment
หากไม่มีรหัส คุณจะไม่สามารถรับอะไรจาก FILES, POST และ GET ได้ คุณจะได้รับพจนานุกรมในวิธีการเหล่านี้เสมอ จึงต้องอาศัยกุญแจในการเข้าถึงอยู่เสมอ - person Neeraj Kumar; 25.04.2019
comment
จะทำอย่างไรถ้าฉันต้องการอัปโหลดจำนวนไฟล์ n? และฝั่ง DRF ไม่ทราบว่า key (เช่น file_1,file_2,file_3 ..etc) ใดที่ใช้ในการส่งไฟล์ n เหล่านั้น นั่นเป็นเหตุผลที่ฉันใช้วิธี .values() - person JPG; 25.04.2019
comment
stackoverflow .com/questions/39645410/ ลองวิธีนี้ดูครับ - person Neeraj Kumar; 25.04.2019
comment
นั่นก็ไม่ได้ช่วยฉันเหมือนกัน อย่างไรก็ตามฉันพบวิธีแก้ปัญหา :) - person JPG; 25.04.2019
comment
@JPG โปรดแบ่งปันวิธีแก้ปัญหา :( - person Shahriar Rahman Zahin; 10.06.2020