2017-08-04 78 views
1

我正在使用DRF后端上传文件。在我的具体情况下,我想要在上传后获取文件名。原因是如果用户上传一个同名的文件,我仍然能够独立处理它。获取多次上传的文件的Django生成的唯一名称

views.py

class ImageUploaderView(viewsets.ModelViewSet): 
    renderer_classes = [renderers.JSONRenderer] 
    queryset = ImageUploader.objects.all() 
    serializer_class = ImageUploaderSerializer 
    parser_classes = (MultiPartParser,) 

serializer.py

class ImageUploaderSerializer(serializers.ModelSerializer): 
    class Meta: 
     model = ImageUploader 

models.py

class ImageUploader(models.Model): 
    # name=models.ImageField(upload_to='media') 
    name=models.FileField(upload_to='media') 

我试着在模型定义之后放置信号和钩子,但是我无法获取这个文件名。有人可以摆脱一些轻松吗?

UPDATE:让我解释我想基本上达到什么:

  • 用户1命中端点 “/ API/calculate_interest_rate”,这是由前端呈现 阵营的组成部分。 “calculate_interest_rate”由 DRF提供服务,并允许用户上传CSV文件。这将被存储为 “user1.csv”,该文件被处理,然后制表(由 React渲染)。

  • 同时和并行用户1,用户2打同一端点他拯救他的文件为“user1.csv”“/ API/calculate_interest_rate”和 错误,并将其上传到systemn。

所以我想能够检测到这两个文件的名称来处理它。通过使用总是相同的默认文件名(例如使用OverwriteStorage()技术),当两个或更多用户使用相同的文件名时,可能会导致混乱。因此,我正在研究一种技术,可以让我按原样获取文件名,并立即处理它。

+0

为什么不使用会话?例如:'user_ .csv'? –

回答

1

如何使用存储选项?

class OverwriteStorage(FileSystemStorage): 
    def get_available_name(self, name, max_length=None): 
     print("filename", name) 
     #parts = name.split('.') you can separate name and extension. 
     return super().get_available_name(name) 

upload_image = models.ImageField(
    upload_to=[yourpath], 
    default=[defaultname], 
    storage=OverwriteStorage() 
) 
+0

我不喜欢覆盖。请检查我的更新以获得澄清。 –

+0

我阅读了您的更新。实际上,如果路径中存在相同的名称文件,Django会自动放置下划线和7个随机字符,以防止保存相同的名称文件。 [source here,get_available_name](https://docs.djangoproject.com/en/1.11/_modules/django/core/files/storage/#Storage.get_available_name)。我只是建议调整它,当你保存时你有相同的文件名。 – Jayground

+0

为什么不把用户PK号码,以便文件名不能与其他文件重复? 'models.FileField(upload_to = your_custom_path)''def your_custom_path(instance,filename):return'user_ {0}'。format(instance.user.id)'如果用像user_user唯一的pk号这样的格式保存文件,不必担心多个用户保存相同的文件名。 – Jayground

0

我建议你到下面这个配置:

1.更改MEDIA_ROOTMEDIA_URL内的settings.py

MEDIA_URL = '/media/' 
MEDIA_ROOT = '/path/to/env/projectname/media' 

2.然后文件,我建议你改变您的upload_to='mediaupload_to='images/%Y/%m/%d,还将name的字段重命名为image

class ImageUploader(models.Model): 
    image = models.FileField(upload_to='images/%Y/%m/%d') 
    # OR 
    # image = models.ImageField(upload_to='images/%Y/%m/%d') 

说明;如果您遵循此配置,您可能已经上传了图像,例如:/media/images/2017/01/29/yourimage.jpg。这是处理重复文件问题的一种方法。

但是如果你想上传有多次不重复的文件的文件,你可以使用deconstructible;

import os, time, uuid 
from django.db import models 
from django.utils.deconstruct import deconstructible 


class ImageUploader(models.Model): 

    @deconstructible 
    class PathAndRename(object): 

     def __init__(self, sub_path): 
      self.path = sub_path 

     def __call__(self, instance, filename): 
      # eg: filename = 'my uploaded file.jpg' 
      ext = filename.split('.')[-1] #eg: '.jpg' 
      uid = uuid.uuid4().hex[:10] #eg: '567ae32f97' 

      # eg: 'my-uploaded-file' 
      new_name = '-'.join(filename.replace('.%s' % ext, '').split()) 

      # eg: 'my-uploaded-file_64c942aa64.jpg' 
      renamed_filename = '%(new_name)s_%(uid)s.%(ext)s' % {'new_name': new_name, 'uid': uid, 'ext': ext} 

      # eg: 'images/2017/01/29/my-uploaded-file_64c942aa64.jpg' 
      return os.path.join(self.path, renamed_filename) 

    image_path = time.strftime('images/%Y/%m/%d') 
    image = models.ImageField(upload_to=PathAndRename(self.image_path)) 
+0

我不想覆盖。另外,考虑到多个用户同时上传。我怎样才能得到文件名,以便我可以处理正确的文件?请检查线程的更新以进行澄清。 –

+0

你可以更新你的意见,特别是在上传功能.. –