I had a need for a file storage system, which would keep the original file name in tact, no matter what. By default, Django’s FileField’s only allow you to base the directory name on the datetime. While this is good for the most part, you can still have duplicate file names if they are added on the same day.
So, after a few headaches, here’s what I call the UsefulFileField:
import os.path import time from django.db import models class UsefulFileField(models.FileField): _path = None def get_filename(self, filename): f = os.path.join(self.get_directory_name(), os.path.basename(filename)) return os.path.normpath(f) def get_directory_name(self): if self._path is None: self._path = os.path.normpath(self.upload_to % tuple(str(float(time.time())).split('.'))) return self._path class UsefulImageField(models.ImageField): _path = None def get_filename(self, filename): f = os.path.join(self.get_directory_name(), os.path.basename(filename)) return os.path.normpath(f) def get_directory_name(self): if self._path is None: self._path = os.path.normpath(self.upload_to % tuple(str(float(time.time())).split('.'))) return self._path
An example use:
class MyModel(models.Model): screenshot = UsefulImageField(upload_to="screenshots/%s/%s/", blank=True, null=True)
2 Responses to "File Fields without Renaming Duplicates"
This is one of many reasons I’m really looking forward to ticket #5361 being checked into trunk as soon as possible. What you’re working toward here would be quite simple (my apologies if the code doesn’t look right.
from django.core.filestorage.filesystem import FileSystemStorage
class UsefulFileStorage(FileSystemStorage):
def get_available_filename(self, filename):
# Leave the filename unmodified
return filename
Then when you want to use it in a model:
from django.db import models
from myapp.storage import UsefulFileStorage
class MyModel(models.Model):
screenshot = models.ImageField(upload_to=”screenshots/%s/%s/”, storage=UsefulFileStorage(), blank=True, null=True)
Mmm nice.
I ended up reworking my filefield’s and just using file = blah and calling .save(). The timestamp stuff was still causing too many directories, and I had to base it off the an id (similar to how we had done it at Curse).
It ends up being screenshots/%s/%s % divmod(id, 1000)
Leave A Reply