在Django REST Framework文件上传中,
我有一个Model,它具有几个字段以及一个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方法更新ModelViewset的URL时, 1.重新启动django服务器时,第一次尝试可以正常进行。先前的附件被覆盖。 2.对该URL的所有后续请求均无效。它只是重命名旧文件,重命名的文件成为当前附件。 3.如果使用PATCH方法,则根本无法访问序列化程序类的validated_data中的keep_previous_attachment。 4.调用instance.save之前,一切都按预期进行。该方法以某种方式引用了旧附件,重命名为其他附件,并将重命名的附件存储为当前附件,而旧附件仍保留在上载文件夹中。
预期结果是: 当用户使用更新视图更新现有条目时, 前一个附件应被覆盖,即删除前一个文件并存储新文件。
我已经覆盖了序列化器类的更新方法,其代码如下。我已经复制粘贴了序列化程序类的原始更新代码,并进行了一些更改。我无法达到预期的结果,因为instance.save方法没有覆盖先前的附件,即即使正在处理新的附件直到调用point 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
请引导我解决。 预先感谢。