2017-08-04 76 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

你可以更新你的意見,特別是在上傳功能.. –