11

Apr

Filed in Code, Django |

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)
  • http://gulopine.gamemusic.org/ Gulopine

    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)

  • David

    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)

blog comments powered by Disqus