【问题标题】:Getting the Django-generated unique name of a file uploaded multiple times获取多次上传的文件的 Django 生成的唯一名称
【发布时间】:2017-08-04 21:15:11
【问题描述】:

我正在使用 DRF 后端上传文件。在我的具体情况下,我希望在文件上传后获取文件名。原因是如果用户上传了同名文件,我仍然可以独立处理。

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')

我试图在模型定义之后放置信号和钩子,但我无法获得这个文件名。有人可以解释一下吗?

更新:让我详细说明我想要实现的基本目标:

  • User1 命中呈现的端点“/api/calculate_interest_rate” 通过前端 React 组件。 “calculate_interest_rate”由 DRF,并让用户上传 CSV 文件。这将存储为 “user1.csv”,文件被处理然后制成表格(由 反应)。

  • 在与 User1 并行的同时,User2 命中相同的端点“/api/calculate_interest_rate”,并且 他错误地将他的文件保存为“user1.csv”,并将其上传到systemn。

所以我希望能够检测文件的两个名称以便处理它。通过始终使用相同的默认文件名(例如使用 OverwriteStorage() 技术),当两个或更多用户使用相同的文件名时,我可能会造成混乱。因此,我正在研究一种允许我按原样获取文件名并立即处理它的技术。

【问题讨论】:

  • 为什么不使用会话?例如:user_<session_key>.csv?

标签: python django django-rest-framework


【解决方案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()
)

【讨论】:

  • 我不想覆盖。请检查我的更新以获得澄清。
  • 我阅读了您的更新。实际上,如果您的路径中有同名文件,Django 会自动添加下划线和 7 个随机字符,以防止保存同名文件。 source here, get_available_name。我只是建议您在保存时具有相同的文件名时对其进行调整。
  • 为什么不输入用户pk号,这样文件名就不能和其他文件重复了? models.FileField(upload_to=your_custom_path)def your_custom_path(instance, filename): return 'user_{0}'.format(instance.user.id)如果你用user_user的唯一pk号这样的格式保存文件,你不用担心多个用户保存相同的文件名。
  • 这实际上是一个很好的策略,我认为它回答了我的问题。
【解决方案2】:

我建议你遵循这个配置:

1. 更改settings.pyMEDIA_ROOTMEDIA_URL 内部文件

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

2.那么,我建议你将upload_to='media改为upload_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。这是处理重复文件问题的一种方法

3.但是如果你想多次上传文件而不重复文件,你可以使用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))

【讨论】:

  • 我不想覆盖。另外,考虑多个用户同时上传。如何获取文件名以便处理正确的文件?请检查线程的更新以获得澄清。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-06-18
  • 2013-04-10
  • 1970-01-01
  • 2017-03-24
  • 2015-01-28
  • 1970-01-01
相关资源
最近更新 更多