Login

Whitelisted overwriting FileSystemStorage

Author:
nickma_at
Posted:
August 9, 2011
Language:
Python
Version:
1.3
Tags:
forms filefield whitelist filestorage overwrite file-extension
Score:
1 (after 1 ratings)

Description A filestorage system that

  • is whitlisted,

  • changes the file name and targeting directory to put the file in - with respect to (runtime) instance information.

  • replaces files if they exists with the same name. Kudos to jedie - http://djangosnippets.org/snippets/977/

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
# -*- coding: UTF-8 -*-
import os
from random import randint
from django.db import models
from django.db.models.fields.files import FileField
from django.utils.translation import ugettext_lazy as _
from django import forms
from django.core.files.storage import FileSystemStorage

class WhitelistedFileField(FileField):
    """Allows white listing of file extensions
    @var ext_whitelist: [tuple] with the endings of the Files e.g. (".wav",)
    """
    def __init__(self, *args, **kwargs):
        """whitelisting
        http://www.djangosnippets.org/snippets/977/"""
        ext_whitelist = kwargs.pop("ext_whitelist")
        self.ext_whitelist = [i.lower() for i in ext_whitelist]
        super(WhitelistedFileField, self).__init__(*args, **kwargs)

    def clean(self, *args, **kwargs):
        """whitelisting"""
        data = super(WhitelistedFileField, self).clean(*args, **kwargs)
        filename = data.name
        ext = os.path.splitext(filename)[1]
        ext = ext.lower()
        if ext not in self.ext_whitelist:
            raise forms.ValidationError("Not allowed filetype!")
        else:
            return data


class OverwritingFileSystemStorage(FileSystemStorage):
    """Overwrites the existing file with the target name 
    
    Take care of the Django development stage
    see: http://groups.google.com/group/django-developers/browse_thread/thread/491619541ba6ac75
    this is going to be updated in further Django versions
    """
    def _save(self, name, *args):
        if self.exists(name):
            self.delete(name)
        return super(OverwritingFileSystemStorage, self)._save(name, *args)
    def get_available_name(self, name):
        return name

AUDIO_FILE_ROOT= '/tmp/django'
fs = OverwritingFileSystemStorage(location=AUDIO_FILE_ROOT) #change the originally MEDIA.ROOT
WHITELIST       = ('mp3',)
def get_uploadTo_place(instance, naturalFilename):
        """Option for FileFields upload directory & name
        Prepares file subDirectory and fileName and returns 
        the whole subpath based on:
        http://adil.2scomplement.com/2009/01/django-playing-with-upload_to-field/
        """
        fileType=       instance.mytype
        try: #try to fetch the fileExtension
            fileExtension =  naturalFilename.rsplit('.',1)[1]
        except IndexError:
            fileExtension = 'unknown'
        
        
        ###Associate admin-filetypes to a path and filetypes to a filename
        #'file_type':'path'
        subDirs = {'music'   : "foo_music", 
                   'ringtone': "foo_ringtone", 
                   'others': "sounds",}
        #'file_type':'file_name'
        fileNames= {'others' : "%i_%s.%s" % (randint(1000,9999), fileType, fileExtension),
                     }
        
        ###Lookup for concrete paths and filenames
        """prepare subDir"""
        if fileType in subDirs: subDir = subDirs[fileType]
        else: subDir = subDirs['others']
        """prepare fileName"""
        if fileType in fileNames: fileName = fileNames[fileType]
        else: 
            fileName = fileNames['others']
        
        return "%s/%s" % (subDir, fileName)


"""USAGE"""
CHOICE_filetype = (
    ("music",      _("music")),
    ("ringtone",   _("ringtone")),
)
class Foosystem(models.Model):
    mytype            = models.CharField(_("audio type"), max_length=15, choices=CHOICE_filetype, )
    audio_file      = WhitelistedFileField(upload_to= get_uploadTo_place, \
                          storage       = fs, \
                          ext_whitelist = WHITELIST, \
                          help_text     = _("Accepted file types are")+ (': %s' % (', '.join(WHITELIST)) ), \
                          verbose_name  = _("Audio File"))

More like this

  1. FileField with file extension whitelist by jedie 6 years, 6 months ago
  2. Admin Apps Names Translation by Nad 5 years, 1 month ago
  3. Overwriting file storage by wolever 4 years, 6 months ago
  4. RESTful class dispatch by Phoenix 5 years, 8 months ago
  5. Admin related widget wrapper with edit / delete link (python widget) by nasp 3 years, 4 months ago

Comments

Please login first before commenting.