Python 在对象ID可用后,如何使用DRF修改FileField以采用不同的路径?
我对DRF文件命名有问题。感兴趣的文件(我相信)是Python 在对象ID可用后,如何使用DRF修改FileField以采用不同的路径?,python,django,django-rest-framework,Python,Django,Django Rest Framework,我对DRF文件命名有问题。感兴趣的文件(我相信)是serializers.py。上载文件时,我希望在对象id可用时在upload_to目录中创建一个目录。覆盖create方法很简单。我还没有弄清楚如何更新数据库中的文件以反映新路径。例如,很容易将文件更改为包含所需路径的字符串,但很难将文件更改为具有所需路径的文件 另外,我知道我正在模糊文件关键字。如果有必要,我会换的 # models.py class TestFile(Model): file = FileField(storage
serializers.py
。上载文件时,我希望在对象id可用时在upload_to
目录中创建一个目录。覆盖create
方法很简单。我还没有弄清楚如何更新数据库中的文件以反映新路径。例如,很容易将文件更改为包含所需路径的字符串,但很难将文件更改为具有所需路径的文件
另外,我知道我正在模糊文件
关键字。如果有必要,我会换的
# models.py
class TestFile(Model):
file = FileField(storage=FileSystemStorage(location=settings.MEDIA_ROOT), upload_to='files', default='{}/files/empty.zip'.format(settings.MEDIA_ROOT))
created_at = CreationDateTimeField()
updated_at = ModificationDateTimeField()
def __str__(self):
return ''.join([str(self.file)])
def __unicode__(self):
return unicode(' '.join([str(self.id)]))
def __id__(self):
return str(self.id)
class Meta:
managed = True
db_table = 'test_files'
verbose_name_plural = 'Test Files'
# viewsets.py
class TestFileViewSet(ModelViewSet):
queryset = TestFile.objects.all()
serializer_class = TestFileSerializer
parser_classes = (MultiPartParser, FormParser)
def perform_create(self, serializer):
serializer.save(file=self.request.data.get('file')
# serializers.py
class TestFileSerializer(ModelSerializer):
file = serializers.FileField(required=True)
def create(self, validated_data):
# Calling create(), this will create the object in the database, making the ID and PK of obj
# available to me.
obj = TestFile.objects.create(**validated_data)
# Creating a new path so that I can use a detail_route in viewset later to GET file
new_path = '/'.join ([str(obj.file).split('/')[0],
str(obj.id),
str(obj.file).split('/')[1]])
# Try to create the parent directory of our destination. This shouldn't fail
try:
os.mkdir(settings.MEDIA_ROOT+ '/files/' +str(obj.id), 0755 )
except:
pass
# Move old file to the new path that we just created.
shutil.copyfile(settings.MEDIA_ROOT + str(obj.file), settings.MEDIA_ROOT + new_path)
# Remove the old file after we have already copied it to new destination
os.rmdir(settings.MEDIA_ROOT + str(obj.file))
# This is where the next step goes!
# What do I need to put in here to make obj.file the correct path now?
return obj
class Meta:
model = TestFile
fields = ( 'id','file','created_at','updated_at')
这就是我在
models.py中输入的内容,以解决我的问题。我将serializers.py
中的相关序列化程序更改为具有默认的create()方法
你能先做obj.file=new_file,然后再做obj.save()?@zaphod100.10吗。
@python_2_unicode_compatible
class TestFile(models.Model):
file = models.FileField(storage=FileSystemStorage(location=settings.MEDIA_ROOT),
upload_to='files/temporary_storage',
blank=True)
created_at = CreationDateTimeField()
updated_at = ModificationDateTimeField()
def save(self, *args, **kwargs):
super(TestFile, self).save(*args, **kwargs)
def __str__(self):
return ' '.join([str(self.file)])
def __unicode__(self):
return unicode(' '.join([str(self.id)]))
def __id__(self):
return str(self.id)
class Meta:
managed = True
db_table = 'test_file'
verbose_name_plural = 'Test Files'
@receiver(post_save, sender=TestFile, dispatch_uid="update_filefield")
def update_file(sender, instance, **kwargs):
filefield = instance.file
if filefield:
filename = filefield.name
new_file_path = ''
if "temporary_storage" in filename:
tmp = filename.split("temporary_storage", 1)
new_file_path = "{}{}{}".format(tmp[0], str(instance.pk), tmp[1])
if new_file_path != filename:
instance.file.storage.delete(new_file_path)
instance.file.storage.save(new_file_path, filefield)
instance.file.name = new_file_path
instance.file.close()
instance.file.storage.delete(filename)
instance.save()