FileField with UUID filename

48 views
Skip to first unread message

Jon Ribbens

unread,
Sep 4, 2016, 11:54:06 AM9/4/16
to Django users
I have a model which basically just represents a file. I want to use a UUID as the filename. I could do the following:

    def _get_filename(instance, filename):
        return str(uuid.uuid4())

   
class File(Model):
       content
= FileField(db_index=True, upload_to=_get_filename)
       filetype
= CharField("MIME Type", max_length=256)

which does work however it is sub-optimal in a couple of ways:
  • the UUID is stored as a VARCHAR in the database
  • the UUID is not used as the primary key
  • there is a pointless additional integer field as the primary key
  • you can't even add unique=True to the field
So I was wondering:
  • why does FileField refuse to allow its use in a unique index or as the primary key?
  • how can I get FileField to use a UUID field in the database?
Any thoughts would be greatly appreciated.

Tim Graham

unread,
Sep 6, 2016, 12:05:39 PM9/6/16
to Django users
See https://code.djangoproject.com/ticket/4345 for the ticket that disallowed primary_key/unique on FileField.

You can write a custom field to get FileField to use a UUID in the database (and likely also lift the other restrictions you want to bypass).

Jon Ribbens

unread,
Sep 6, 2016, 12:45:36 PM9/6/16
to Django users
On Tuesday, 6 September 2016 17:05:39 UTC+1, Tim Graham wrote:
See https://code.djangoproject.com/ticket/4345 for the ticket that disallowed primary_key/unique on FileField.

I've now opened a new ticket #27188 to suggest reversing this change ;-)
 
You can write a custom field to get FileField to use a UUID in the database (and likely also lift the other restrictions you want to bypass).

Yes, I was wondering how to do that because it's not at all obvious. However I have since decided that I simply need a custom Storage class like this:

class ChecksumStorage(FileSystemStorage):
   
"""Store files in the file system with filename based on file contents."""
   
def save(self, name, content, max_length=None):
        checksum
= hashlib.sha256()
       
for data in content.chunks():
            checksum
.update(data)
       
return super().save(checksum.hexdigest(), content)

and then I don't need a model at all, I can just refer to the files with a CharField(max_length=64).
Reply all
Reply to author
Forward
0 new messages