3

My goal is that each time a user uploads a file to the media folder, that the previous file is deleted and replaced with the current. Essentially I only want a single file in the folder at a time. I have a working example that overwrites a file within the folder if it contains the same name and I figure that a simple modification to it would yield a solution, but I have't been able to correctly implement the modification.

The code I have to overwrite duplicates is as follows:

Models.py

class OverwriteStorage(FileSystemStorage):
    def get_available_name(self, name):
        if self.exists(name):
            os.remove(os.path.join(settings.MEDIA_ROOT, name))
        return name
class FileUpload(models.Model):
    docFile = models.FileField(upload_to='Data_Files', storage=OverwriteStorage(), blank=True)

    def __str__(self):
        return self.docfile.name

    @property
    def filename(self):
        return os.path.basename(self.docFile.name)

Any ideas on modifications or other potential solutions would be greatly appreciated.

Community
  • 1
  • 1
alacy
  • 4,972
  • 8
  • 30
  • 47
  • 1
    see here http://stackoverflow.com/questions/2673647/enforce-unique-upload-file-names-using-django – sax Dec 15 '14 at 21:33
  • Perhaps I poorly phrased my question. I don't need each file to have a unique name, but rather each time a file is uploaded the file that is previously in the media folder is deleted. In other words, there should never be more than 1 file within that folder because it should always been overwritten by the newly uploaded file. – alacy Dec 15 '14 at 21:38
  • if you use the one filename per "record" (ie using the record pk) each upload will overwrite the exiting one – sax Dec 15 '14 at 21:40
  • I'm struggling to understand what you mean. Could you demonstrate an example? – alacy Dec 15 '14 at 21:53

2 Answers2

2

Do it like this:

class FileUpload(models.Model):
    docFile = models.FileField(upload_to=path_file())

And here is the function that handles your upload:

def path_file():
    def wrapper(user, filename):
        file_upload_dir = os.path.join(settings.MEDIA_ROOT, 'file_upload')
        if os.path.exists(file_upload_dir):
            import shutil
            shutil.rmtree(file_upload_dir)
        return os.path.join(file_upload_dir, filename)
    return wrapper

There you go. So the idea is simple. Any file that get uploaded will arrive in a well defined directory. Delete and recreate this directory every time an upload happens

I also suggest you that you rename the name of the uploaded file to whatever you want. Something like single_file.extension

alacy
  • 4,972
  • 8
  • 30
  • 47
Mihai Zamfir
  • 2,167
  • 4
  • 22
  • 37
  • I made a single edit, but besides that your code worked perfectly. Thanks! – alacy Dec 15 '14 at 22:27
  • 1
    yep, forgot to specify the path of ``rmtree``. You can also put your directories under specific user directories as you have access to the ``user`` variable. In case that you have more users – Mihai Zamfir Dec 15 '14 at 22:32
  • note that 1) this code is not thread-safe 2) you don't need to wrap your `wrapper()` simply use `models.FileField(upload_to=wrapper`) – sax Dec 16 '14 at 07:32
2

I managed to delete a media file easily using Django FileSystemStorage in Django==3.2. All you need to do is pass the absolute path of the file you want to delete into fs.delete(absolute_path) The absolute path can also be easily obtained from fs.path(filename)

from django.core.files.storage import FileSystemStorage

img_file = request.FILES['file']
fs = FileSystemStorage()
filename = fs.save(img_file.name, img_file)
uploaded_file_path = fs.path(filename)
""" 
   now that you have the absolute path
   you can just pass this to fs.delete(absolute_path) anytime
   to delete that particular media file like so,
"""
fs.delete(uploaded_file_path)
because_im_batman
  • 975
  • 10
  • 26