Несколько загрузок файлов DRF

только ради свойств объекта мыслящего объекта из временной шкалы:

var foo = {
    a: function(){return 5}(),
    b: function(){return 6}(),
    c: function(){return this.a + this.b}
}

console.log(foo.c())

также есть более высокие ответы . Вот как я модифицировал пример кода, с которым вы допросили.

UPDATE:

var foo = {
    get a(){return 5},
    get b(){return 6},
    get c(){return this.a + this.b}
}
// console.log(foo.c);
10
задан geekscrap 26 March 2019 в 22:47
поделиться

1 ответ

Возможный дубликат --- Django REST: загрузка и сериализация нескольких изображений . ​​



Из документа Записываемый встраиваемый сериализатор DRF ,

По умолчанию вложенные сериализаторы доступны только для чтения. Если вы хотите поддерживать операции записи во вложенном поле сериализатора, вам нужно создать методы create() и / или update() , чтобы явно указывало, как отношения ребенка должны быть сохранены.

Из этого ясно, что дочерний сериализатор (BinaryFileSerializer) не будет вызывать свой собственный метод create(), если не вызывается явно.

Цель вашего запроса HTTP POST - создать новый экземпляр Submission (и экземпляр BinaryFile ) , Процесс создания проходит по методу create() сериализатора SubmissionCreateSerializer , который вы должны переопределить. Таким образом, он будет действовать / выполняться в соответствии с вашим кодом.


ОБНОВЛЕНИЕ-1

Что нужно запомнить
1. AFAIK, мы не можем отправить вложенных multipart/form-data [ 1165]
2. Здесь я только пытаюсь реализовать сценарий наименьшего случая
3. Я тестирую это решение с POSTMAN Инструмент тестирования остальных API.
4. Этот метод может быть сложным (пока мы не нашли лучший).
5. Предполагая, что ваш класс представления является подклассом класса ModelViewSet


[1146] Что я собираюсь делать? [1198 ]
1. Поскольку мы не можем отправлять файлы / данные во вложенном виде, мы должны отправлять их в плоском режиме.

image-1
img-1

2. Переопределите метод __init__() сериализатора SubmissionSerializer и динамически добавьте столько же атрибута FileField() в соответствии с request.FILES [11103 ] data.
Мы могли бы как-то использовать здесь ListSerializer или ListField . К сожалению, я не смог найти способ: (

# init method of "SubmissionSerializer"
def __init__(self, *args, **kwargs):
    file_fields = kwargs.pop('file_fields', None)
    super().__init__(*args, **kwargs)
    if file_fields:
        field_update_dict = {field: serializers.FileField(required=False, write_only=True) for field in file_fields}
        self.fields.update(**field_update_dict)

Итак, что здесь ID file_fields?
Поскольку форма -data - это пара ключ-значение , все данные файла должны быть связаны с ключом. Здесь, в image-1 , вы можете увидеть file_1 и file_2.

3. Теперь нам нужно передать значения file_fields из view. Так как эта операция создает новый экземпляр, нам нужно переопределить create() Метод API-класса .

# complete view code
from rest_framework import status
from rest_framework import viewsets


class SubmissionAPI(viewsets.ModelViewSet):
    queryset = Submission.objects.all()
    serializer_class = SubmissionSerializer

    def create(self, request, *args, **kwargs):
        # main thing starts
        file_fields = list(request.FILES.keys())  # list to be passed to the serializer
        serializer = self.get_serializer(data=request.data, file_fields=file_fields)
        # main thing ends

        serializer.is_valid(raise_exception=True)
        self.perform_create(serializer)
        headers = self.get_success_headers(serializer.data)
        return Response(serializer.data, status=status.HTTP_201_CREATED, headers=headers)


4. Теперь все значения будут правильно сериализованы. Настало время переопределить [ 11112] create() метод SubmissionSerializer() для сопоставления отношений

def create(self, validated_data):
    from django.core.files.uploadedfile import InMemoryUploadedFile
    validated_data_copy = validated_data.copy()
    validated_files = []
    for key, value in validated_data_copy.items():
        if isinstance(value, InMemoryUploadedFile):
            validated_files.append(value)
            validated_data.pop(key)
    submission_instance = super().create(validated_data)
    for file in validated_files:
        BinaryFile.objects.create(submission=submission_instance, file=file)
    return submission_instance



5. Вот и все! !!


Полный фрагмент кода

# serializers.py
from rest_framework import serializers
from django.core.files.uploadedfile import InMemoryUploadedFile


class SubmissionSerializer(serializers.ModelSerializer):
    def __init__(self, *args, **kwargs):
        file_fields = kwargs.pop('file_fields', None)
        super().__init__(*args, **kwargs)
        if file_fields:
            field_update_dict = {field: serializers.FileField(required=False, write_only=True) for field in file_fields}
            self.fields.update(**field_update_dict)

    def create(self, validated_data):
        validated_data_copy = validated_data.copy()
        validated_files = []
        for key, value in validated_data_copy.items():
            if isinstance(value, InMemoryUploadedFile):
                validated_files.append(value)
                validated_data.pop(key)
        submission_instance = super().create(validated_data)
        for file in validated_files:
            BinaryFile.objects.create(submission=submission_instance, file=file)
        return submission_instance

    class Meta:
        model = Submission
        fields = '__all__'


# views.py
from rest_framework import status
from rest_framework import viewsets


class SubmissionAPI(viewsets.ModelViewSet):
    queryset = Submission.objects.all()
    serializer_class = SubmissionSerializer

    def create(self, request, *args, **kwargs):
        # main thing starts
        file_fields = list(request.FILES.keys())  # list to be passed to the serializer
        serializer = self.get_serializer(data=request.data, file_fields=file_fields)
        # main thing ends

        serializer.is_valid(raise_exception=True)
        self.perform_create(serializer)
        headers = self.get_success_headers(serializer.data)
        return Response(serializer.data, status=status.HTTP_201_CREATED, headers=headers)

Снимки экрана и другие материалы

1. Консоль POSTMAN
[ 1160] POSTMAN console
2. Джанго Шелл

In [2]: Submission.objects.all()                                                                                                                                                                                   
Out[2]: <QuerySet [<Submission: Submission object>]>

In [3]: sub_obj = Submission.objects.all()[0]                                                                                                                                                                      

In [4]: sub_obj                                                                                                                                                                                                    
Out[4]: <Submission: Submission object>

In [5]: sub_obj.__dict__                                                                                                                                                                                           
Out[5]: 
{'_state': <django.db.models.base.ModelState at 0x7f529a7ea240>,
 'id': 5,
 'issued_at': datetime.datetime(2019, 3, 27, 8, 45, 42, 193943, tzinfo=<UTC>),
 'completed': False,
 'atomic_id': 1}

In [6]: sub_obj.binary_files.all()                                                                                                                                                                                 
Out[6]: <QuerySet [<BinaryFile: uploads/binary/logo-800.png>, <BinaryFile: uploads/binary/Doc.pdf>, <BinaryFile: uploads/binary/invoice_2018_11_29_04_57_53.pdf>, <BinaryFile: uploads/binary/Screenshot_from_2019-02-13_16-22-53.png>]>

In [7]: for _ in sub_obj.binary_files.all(): 
   ...:     print(_) 
   ...:                                                                                                                                                                                                            
uploads/binary/logo-800.png
uploads/binary/Doc.pdf
uploads/binary/invoice_2018_11_29_04_57_53.pdf
uploads/binary/Screenshot_from_2019-02-13_16-22-53.png
[118 3]
3. Скриншот Django Admin enter image description here

0
ответ дан JPG 26 March 2019 в 22:47
поделиться
Другие вопросы по тегам:

Похожие вопросы: