1from __future__ import unicode_literals 2from future.builtins import str, super 3 4import os 5import datetime 6 7from django import forms 8from django.conf import settings 9from django.core.files.storage import default_storage 10from django.db.models.fields import Field 11from django.db.models.fields.files import FileDescriptor 12from django.forms.widgets import Input 13from django.template.loader import render_to_string 14from django.utils.encoding import smart_str 15from django.utils.translation import ugettext_lazy as _ 16 17from filebrowser_safe.settings import * 18from filebrowser_safe.base import FieldFileObject 19from filebrowser_safe.functions import get_directory 20 21 22class FileBrowseWidget(Input): 23 input_type = 'text' 24 25 class Media: 26 js = (os.path.join(URL_FILEBROWSER_MEDIA, 'js/AddFileBrowser.js'), ) 27 28 def __init__(self, attrs=None): 29 self.directory = attrs.get('directory', '') 30 self.extensions = attrs.get('extensions', '') 31 self.format = attrs.get('format', '') 32 if attrs is not None: 33 self.attrs = attrs.copy() 34 else: 35 self.attrs = {} 36 37 def render(self, name, value, attrs=None): 38 if value is None: 39 value = "" 40 directory = self.directory 41 if self.directory: 42 if callable(self.directory): 43 directory = self.directory() 44 directory = os.path.normpath(datetime.datetime.now().strftime(directory)) 45 fullpath = os.path.join(get_directory(), directory) 46 if not default_storage.isdir(fullpath): 47 default_storage.makedirs(fullpath) 48 final_attrs = dict(type=self.input_type, name=name, **attrs) 49 final_attrs['search_icon'] = URL_FILEBROWSER_MEDIA + 'img/filebrowser_icon_show.gif' 50 final_attrs['directory'] = directory 51 final_attrs['extensions'] = self.extensions 52 final_attrs['format'] = self.format 53 final_attrs['DEBUG'] = DEBUG 54 return render_to_string("filebrowser/custom_field.html", dict(locals(), MEDIA_URL=MEDIA_URL)) 55 56 57class FileBrowseFormField(forms.CharField): 58 widget = FileBrowseWidget 59 60 default_error_messages = { 61 'extension': _(u'Extension %(ext)s is not allowed. Only %(allowed)s is allowed.'), 62 } 63 64 def __init__(self, max_length=None, min_length=None, 65 directory=None, extensions=None, format=None, 66 *args, **kwargs): 67 self.max_length, self.min_length = max_length, min_length 68 self.directory = directory 69 self.extensions = extensions 70 if format: 71 self.format = format or '' 72 self.extensions = extensions or EXTENSIONS.get(format) 73 super(FileBrowseFormField, self).__init__(*args, **kwargs) 74 75 def clean(self, value): 76 value = super(FileBrowseFormField, self).clean(value) 77 if value == '': 78 return value 79 file_extension = os.path.splitext(value)[1].lower().split("?")[0] 80 if self.extensions and not file_extension in self.extensions: 81 raise forms.ValidationError(self.error_messages['extension'] % {'ext': file_extension, 'allowed': ", ".join(self.extensions)}) 82 return value 83 84 85class FileBrowseField(Field): 86 # These attributes control how the field is accessed on a model instance. 87 # Due to contribute_to_class, FileDescriptor will cause this field to be 88 # represented by a FileFieldObject on model instances. 89 # Adapted from django.db.models.fields.files.FileField. 90 attr_class = FieldFileObject 91 descriptor_class = FileDescriptor 92 93 def __init__(self, *args, **kwargs): 94 self.directory = kwargs.pop('directory', '') 95 self.extensions = kwargs.pop('extensions', '') 96 self.format = kwargs.pop('format', '') 97 self.storage = kwargs.pop('storage', default_storage) 98 super(FileBrowseField, self).__init__(*args, **kwargs) 99 100 def get_db_prep_value(self, value, connection, prepared=False): 101 if value is None: 102 return None 103 return smart_str(value) 104 105 def get_manipulator_field_objs(self): 106 return [oldforms.TextField] 107 108 def get_internal_type(self): 109 return "CharField" 110 111 def formfield(self, **kwargs): 112 attrs = { 113 'directory': self.directory, 114 'extensions': self.extensions, 115 'format': self.format, 116 'storage': self.storage, 117 } 118 defaults = { 119 'form_class': FileBrowseFormField, 120 'widget': FileBrowseWidget(attrs=attrs), 121 'directory': self.directory, 122 'extensions': self.extensions, 123 'format': self.format 124 } 125 defaults.update(kwargs) 126 return super(FileBrowseField, self).formfield(**defaults) 127 128 def contribute_to_class(self, cls, name, **kwargs): 129 """ 130 From django.db.models.fields.files.FileField.contribute_to_class 131 """ 132 super(FileBrowseField, self).contribute_to_class(cls, name, **kwargs) 133 setattr(cls, self.name, self.descriptor_class(self)) 134