Django REST Framework Загрузка файлов не работает - PullRequest
1 голос
/ 06 марта 2019

В загружаемых файлах Django REST Framework,

У меня есть одна модель, которая имеет пару полей вместе с FileField, который является вложением, которое является необязательным.

class Task(model.Model):
    attachment = models.FileField(upload_to=default_location, null=True, blank=True)
    ... some extra fields

Для этой модели существует ModelViewset для реализации функций CRUD. Пользователь может создать запись в модели с / без вложения.

class TaskViewSet(viewsets.ModelViewSet):
    serializer_class = TaskSerializer

    def get_queryset(self):
        return Task.objects.all()

У Serilaizer есть дополнительное BooleanField, чтобы решить, сохранять ли последнее вложение или нет. Это поле будет отображаться как флажок в переднем конце.

class TaskSerializer(serializers.ModelSerializer):
    keep_previous_attachment = serializers.BooleanField(default=False)

    class Meta: 
        model = Task
        fields = ['id','attachment', 'heading']

Когда пользователь создает новую запись, она работает как положено. он сохраняет вложение в своем местоположении по умолчанию. Когда пользователь обновляет запись с / без вложения, все работает не так, как ожидалось.

Когда я использую метод PUT для обновления URL-адреса ModelViewset, 1. Когда сервер django перезапускается, первая попытка работает нормально. Предыдущее вложение перезаписывается. 2. Все последующие запросы к URL не работают. Он просто переименовывает старый файл и переименованный файл становится текущим вложением. 3. Если я использую метод PATCH, я вообще не могу получить доступ к keep_previous_attachment в validated_data класса сериализатора. 4. Все работает как ожидалось до вызова instance.save. Этот метод каким-то образом ссылается на старое вложение, переименовывает его во что-то еще и сохраняет переименованное вложение в качестве текущего вложения, а старое вложение все еще находится в папке загрузки.

Ожидаемый результат: Когда пользователь обновляет существующую запись, используя представления обновления, предыдущее вложение должно быть перезаписано, т.е. удалить предыдущий файл и сохранить новый.

Я переписал метод обновления в классе сериализатора, код которого приведен ниже. Я скопировал, вставил оригинальный код обновления класса сериализатора и внес некоторые изменения. Я не могу достичь ожидаемого результата, так как метод instance.save не перезаписывает предыдущее вложение, т.е. он все еще сохраняет предыдущее вложение, даже когда новое вложение обрабатывается до тех пор, пока не будет вызван точечный метод instance.save. Я пробовал с передачей, force_update = True, он тоже не работает. Я не могу обернуть голову, что здесь не так.

def update(self, instance, validated_data):

    from rest_framework.serializers import raise_errors_on_nested_writes
    raise_errors_on_nested_writes('update', self, validated_data)

    from rest_framework.utils import model_meta
    info = model_meta.get_field_info(instance)

    keep_old = validated_data.pop("keep_previous_attachment")
    validated_attachment = validated_data.pop("attachment")

    # Simply set each attribute on the instance, and then save it.
    # Note that unlike `.create()` we don't need to treat many-to-many
    # relationships as being a special case. During updates we already
    # have an instance pk for the relationships to be associated with.

    for attr, value in validated_data.items():
        if attr in info.relations and info.relations[attr].to_many:
            field = getattr(instance, attr)
            field.set(value)
        else:
            setattr(instance, attr, value)

    if keep_old is False:

        # delete the references to the older attachment
        instance.attachment = None 
        instance.save()


        deletion_path = os.path.join("location_of_folder")

        deleted = delete_task_attachments(deletion_path, request)

        instance.attachment = validated_attachment

    # if keep_old is True:
    #     instance.attachment is untouched by the code, so no update will happen.

    # print()
    # print("BEFORE SAVE")
    # print("instance.attachment")
    # print(instance.attachment)
    # print()

    instance.save()

    # print()
    # print("After SAVE")
    # print("instance.attachment")
    # print(instance.attachment)
    # print()

    return instance

Пожалуйста, приведите меня к решению. Заранее спасибо.

...