James
James

Reputation: 3815

Getting the Django-generated unique name of a file uploaded multiple times

I am using DRF backend to upload files. In my specific case I will want to get the name of the file, after it has been uploaded. The reason is that if a user uploads a file with same name, I am still able to process it independently.

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

I tried to put signals and hooks after the model definitions but I am not being able to get this filename. Can someone shed some light pls?

UPDATE: Let me elaborate what I want to achieve essentially:

So I want to be able to detect both names of the file in order to process it. By using always the same default filename (ex. using the OverwriteStorage() technique), I will probably cause chaos when two or more users are using the same filename. Therefore I am looking into a technique that allows me to get the filename as is, and process it immediately.

Upvotes: 1

Views: 2281

Answers (2)

binpy
binpy

Reputation: 4194

I suggest you to following this configuration:

1. Change your MEDIA_ROOT and MEDIA_URL inside file of settings.py

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

2. Then, I suggest you to change your upload_to='media to upload_to='images/%Y/%m/%d, also rename your field of name with image.

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

Explanation; If you following this configuration, you could have uploaded images are following, eg: /media/images/2017/01/29/yourimage.jpg. This is one way to handle the problem of duplicated files.

3. But if you want to upload file with multiple times without duplicate files, you can using 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))

Upvotes: 0

Jayground
Jayground

Reputation: 1877

How about using storage option?

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

Upvotes: 1

Related Questions