Ticket #5361: filestorage.16.diff
File filestorage.16.diff, 69.9 KB (added by , 17 years ago) |
---|
-
django/conf/global_settings.py
216 216 # Path to the "jing" executable -- needed to validate XMLFields 217 217 JING_PATH = "/usr/bin/jing" 218 218 219 # Default file storage mechanism that holds media. 220 DEFAULT_FILE_STORAGE = 'django.core.filestorage.filesystem.FileSystemStorage' 221 219 222 # Absolute path to the directory that holds media. 220 223 # Example: "/home/media/media.lawrence.com/" 221 224 MEDIA_ROOT = '' -
django/core/filestorage/__init__.py
Property changes on: django/core/filestorage ___________________________________________________________________ Name: svn:ignore + *.pyc
1 from django.conf import settings 2 from django.core.exceptions import ImproperlyConfigured 3 4 def get_storage(import_path): 5 try: 6 dot = import_path.rindex('.') 7 except ValueError: 8 raise ImproperlyConfigured("%s isn't a storage module." % import_path) 9 module, classname = import_path[:dot], import_path[dot+1:] 10 try: 11 mod = __import__(module, {}, {}, ['']) 12 except ImportError, e: 13 raise ImproperlyConfigured('Error importing storage module %s: "%s"' % (module, e)) 14 try: 15 storage_class = getattr(mod, classname) 16 except AttributeError: 17 raise ImproperlyConfigured('Storage module "%s" does not define a "%s" class.' % (module, classname)) 18 return storage_class() 19 20 storage = get_storage(settings.DEFAULT_FILE_STORAGE) -
django/core/filestorage/base.py
1 from StringIO import StringIO 2 3 from django.utils.text import get_valid_filename 4 5 class Storage(object): 6 def get_valid_filename(self, filename): 7 return get_valid_filename(filename) 8 9 def get_available_filename(self, filename): 10 # If the filename already exists, keep adding an underscore to the name 11 # of the file until the filename doesn't exist. 12 while self.exists(filename): 13 try: 14 dot_index = filename.rindex('.') 15 except ValueError: # filename has no dot 16 filename += '_' 17 else: 18 filename = filename[:dot_index] + '_' + filename[dot_index:] 19 return filename 20 21 class RemoteFile(StringIO): 22 """Sends files to remote storage automatically, when necessary.""" 23 24 def __init__(self, data, mode, writer): 25 self._mode = mode 26 self._write_to_storage = writer 27 self._is_dirty = False 28 StringIO.__init__(self, data) 29 30 def write(self, data): 31 if 'w' not in self._mode: 32 raise AttributeError("File was opened for read-only access.") 33 StringIO.write(self, data) 34 self._is_dirty = True 35 36 def close(self): 37 if self._is_dirty: 38 self._write_to_storage(self.getvalue()) 39 StringIO.close(self) -
django/core/filestorage/filesystem.py
1 import os 2 import urlparse 3 4 from django.conf import settings 5 from django.core.exceptions import SuspiciousOperation 6 from django.utils.encoding import force_unicode, smart_str 7 from django.core.filestorage.base import Storage 8 from django.utils.text import force_unicode 9 from django.utils._os import safe_join 10 11 class FileSystemStorage(Storage): 12 """Standard filesystem storage""" 13 14 def __init__(self, location=settings.MEDIA_ROOT, base_url=settings.MEDIA_URL): 15 self.location = os.path.abspath(location) 16 self.base_url = base_url 17 18 def path(self, filename): 19 try: 20 path = safe_join(self.location, filename) 21 except ValueError: 22 raise SuspiciousOperation("Attempted access to '%s' denied." % filename) 23 return os.path.normpath(path) 24 25 def filesize(self, filename): 26 return os.path.getsize(self.path(filename)) 27 28 def url(self, filename): 29 return urlparse.urljoin(self.base_url, filename).replace('\\', '/') 30 31 def exists(self, filename): 32 return os.path.exists(self.path(filename)) 33 34 def open(self, filename, mode='rb'): 35 return open(self.path(filename), mode) 36 37 def save(self, filename, raw_contents): 38 directory = self.path(os.path.dirname(filename)) 39 if not os.path.exists(directory): 40 os.makedirs(directory) 41 elif not os.path.isdir(directory): 42 raise IOError("%s exists and is not a directory." % directory) 43 44 filename = self.get_available_filename(filename) 45 46 # Write the file to disk. 47 fp = self.open(filename, 'wb') 48 fp.write(raw_contents) 49 fp.close() 50 51 # Store filenames with forward slashes, even on Windows 52 return force_unicode(filename.replace('\\', '/')) 53 54 def delete(self, filename): 55 file_name = self.path(filename) 56 # If the file exists, delete it from the filesystem. 57 if os.path.exists(file_name): 58 os.remove(file_name) -
django/db/models/__init__.py
8 8 from django.db.models.base import Model, AdminOptions 9 9 from django.db.models.fields import * 10 10 from django.db.models.fields.subclassing import SubfieldBase 11 from django.db.models.fields.files import FileField, ImageField 11 12 from django.db.models.fields.related import ForeignKey, OneToOneField, ManyToManyField, ManyToOneRel, ManyToManyRel, OneToOneRel, TABULAR, STACKED 12 13 from django.db.models import signals 13 14 from django.utils.functional import curry -
django/db/models/base.py
8 8 import django.db.models.manager # Ditto. 9 9 from django.core import validators 10 10 from django.core.exceptions import ObjectDoesNotExist, MultipleObjectsReturned, FieldError 11 from django.db.models.fields import AutoField, ImageField,FieldDoesNotExist11 from django.db.models.fields import AutoField, FieldDoesNotExist 12 12 from django.db.models.fields.related import OneToOneRel, ManyToOneRel, OneToOneField 13 13 from django.db.models.query import delete_objects, Q 14 14 from django.db.models.options import Options, AdminOptions … … 20 20 from django.utils.functional import curry 21 21 from django.utils.encoding import smart_str, force_unicode, smart_unicode 22 22 from django.conf import settings 23 from warnings import warn 23 24 24 25 try: 25 26 set … … 432 433 return getattr(self, cachename) 433 434 434 435 def _get_FIELD_filename(self, field): 435 if getattr(self, field.attname): # value is not blank 436 return os.path.join(settings.MEDIA_ROOT, getattr(self, field.attname)) 437 return '' 436 warn("instance.get_%s_filename() is deprecated. Use instance.%s.path() instead." % \ 437 (field.attname, field.attname), DeprecationWarning) 438 try: 439 return getattr(self, field.attname).path() 440 except ValueError: 441 # For backward compatibility 442 return settings.MEDIA_ROOT 438 443 439 444 def _get_FIELD_url(self, field): 440 if getattr(self, field.attname): # value is not blank 441 import urlparse 442 return urlparse.urljoin(settings.MEDIA_URL, getattr(self, field.attname)).replace('\\', '/') 443 return '' 445 warn("instance.get_%s_url() is deprecated. Use instance.%s.url() instead." % \ 446 (field.attname, field.attname), DeprecationWarning) 447 try: 448 return getattr(self, field.attname).url() 449 except ValueError: 450 # For backward compatibility 451 return settings.MEDIA_URL 444 452 445 453 def _get_FIELD_size(self, field): 446 return os.path.getsize(self._get_FIELD_filename(field)) 454 warn("instance.get_%s_size() is deprecated. Use instance.%s.filesize() instead." % \ 455 (field.attname, field.attname), DeprecationWarning) 456 return getattr(self, field.attname).filesize() 447 457 448 458 def _save_FIELD_file(self, field, filename, raw_contents, save=True): 449 directory = field.get_directory_name() 450 try: # Create the date-based directory if it doesn't exist. 451 os.makedirs(os.path.join(settings.MEDIA_ROOT, directory)) 452 except OSError: # Directory probably already exists. 453 pass 454 filename = field.get_filename(filename) 459 warn("instance.save_%s_file() is deprecated. Use instance.%s.save() instead." % \ 460 (field.attname, field.attname), DeprecationWarning) 461 return getattr(self, field.attname).save(filename, raw_contents, save) 455 462 456 # If the filename already exists, keep adding an underscore to the name of457 # the file until the filename doesn't exist.458 while os.path.exists(os.path.join(settings.MEDIA_ROOT, filename)):459 try:460 dot_index = filename.rindex('.')461 except ValueError: # filename has no dot462 filename += '_'463 else:464 filename = filename[:dot_index] + '_' + filename[dot_index:]465 466 # Write the file to disk.467 setattr(self, field.attname, filename)468 469 full_filename = self._get_FIELD_filename(field)470 fp = open(full_filename, 'wb')471 fp.write(raw_contents)472 fp.close()473 474 # Save the width and/or height, if applicable.475 if isinstance(field, ImageField) and (field.width_field or field.height_field):476 from django.utils.images import get_image_dimensions477 width, height = get_image_dimensions(full_filename)478 if field.width_field:479 setattr(self, field.width_field, width)480 if field.height_field:481 setattr(self, field.height_field, height)482 483 # Save the object because it has changed unless save is False484 if save:485 self.save()486 487 _save_FIELD_file.alters_data = True488 489 463 def _get_FIELD_width(self, field): 490 return self._get_image_dimensions(field)[0] 464 warn("instance.get_%s_width() is deprecated. Use instance.%s.width() instead." % \ 465 (field.attname, field.attname), DeprecationWarning) 466 return getattr(self, field.attname).width() 491 467 492 468 def _get_FIELD_height(self, field): 493 return self._get_image_dimensions(field)[1] 469 warn("instance.get_%s_height() is deprecated. Use instance.%s.height() instead." % \ 470 (field.attname, field.attname), DeprecationWarning) 471 return getattr(self, field.attname).height() 494 472 495 def _get_image_dimensions(self, field):496 cachename = "__%s_dimensions_cache" % field.name497 if not hasattr(self, cachename):498 from django.utils.images import get_image_dimensions499 filename = self._get_FIELD_filename(field)500 setattr(self, cachename, get_image_dimensions(filename))501 return getattr(self, cachename)502 503 473 ############################################ 504 474 # HELPER FUNCTIONS (CURRIED MODEL METHODS) # 505 475 ############################################ -
django/db/models/fields/__init__.py
1 1 import copy 2 2 import datetime 3 import os4 3 import time 5 4 try: 6 5 import decimal … … 306 305 name_prefix is a prefix to prepend to the "field_name" argument. 307 306 rel is a boolean specifying whether this field is in a related context. 308 307 """ 308 from django.db.models.fields import files 309 309 310 field_objs, params = self.prepare_field_objs_and_params(manipulator, name_prefix) 310 311 311 312 # Add the "unique" validator(s). … … 337 338 # If this field is in a related context, check whether any other fields 338 339 # in the related object have core=True. If so, add a validator -- 339 340 # RequiredIfOtherFieldsGiven -- to this FormField. 340 if rel and not self.blank and not isinstance(self, AutoField) and not isinstance(self, FileField):341 if rel and not self.blank and not isinstance(self, AutoField) and not isinstance(self, files.FileField): 341 342 # First, get the core fields, if any. 342 343 core_field_names = [] 343 344 for f in opts.fields: … … 749 750 defaults.update(kwargs) 750 751 return super(EmailField, self).formfield(**defaults) 751 752 752 class FileField(Field):753 def __init__(self, verbose_name=None, name=None, upload_to='', **kwargs):754 self.upload_to = upload_to755 kwargs['max_length'] = kwargs.get('max_length', 100)756 Field.__init__(self, verbose_name, name, **kwargs)757 758 def get_internal_type(self):759 return "FileField"760 761 def get_db_prep_save(self, value):762 "Returns field's value prepared for saving into a database."763 # Need to convert UploadedFile objects provided via a form to unicode for database insertion764 if value is None:765 return None766 return unicode(value)767 768 def get_manipulator_fields(self, opts, manipulator, change, name_prefix='', rel=False, follow=True):769 field_list = Field.get_manipulator_fields(self, opts, manipulator, change, name_prefix, rel, follow)770 if not self.blank:771 if rel:772 # This validator makes sure FileFields work in a related context.773 class RequiredFileField(object):774 def __init__(self, other_field_names, other_file_field_name):775 self.other_field_names = other_field_names776 self.other_file_field_name = other_file_field_name777 self.always_test = True778 def __call__(self, field_data, all_data):779 if not all_data.get(self.other_file_field_name, False):780 c = validators.RequiredIfOtherFieldsGiven(self.other_field_names, ugettext_lazy("This field is required."))781 c(field_data, all_data)782 # First, get the core fields, if any.783 core_field_names = []784 for f in opts.fields:785 if f.core and f != self:786 core_field_names.extend(f.get_manipulator_field_names(name_prefix))787 # Now, if there are any, add the validator to this FormField.788 if core_field_names:789 field_list[0].validator_list.append(RequiredFileField(core_field_names, field_list[1].field_name))790 else:791 v = validators.RequiredIfOtherFieldNotGiven(field_list[1].field_name, ugettext_lazy("This field is required."))792 v.always_test = True793 field_list[0].validator_list.append(v)794 field_list[0].is_required = field_list[1].is_required = False795 796 # If the raw path is passed in, validate it's under the MEDIA_ROOT.797 def isWithinMediaRoot(field_data, all_data):798 f = os.path.abspath(os.path.join(settings.MEDIA_ROOT, field_data))799 if not f.startswith(os.path.abspath(os.path.normpath(settings.MEDIA_ROOT))):800 raise validators.ValidationError, _("Enter a valid filename.")801 field_list[1].validator_list.append(isWithinMediaRoot)802 return field_list803 804 def contribute_to_class(self, cls, name):805 super(FileField, self).contribute_to_class(cls, name)806 setattr(cls, 'get_%s_filename' % self.name, curry(cls._get_FIELD_filename, field=self))807 setattr(cls, 'get_%s_url' % self.name, curry(cls._get_FIELD_url, field=self))808 setattr(cls, 'get_%s_size' % self.name, curry(cls._get_FIELD_size, field=self))809 setattr(cls, 'save_%s_file' % self.name, lambda instance, filename, raw_contents, save=True: instance._save_FIELD_file(self, filename, raw_contents, save))810 dispatcher.connect(self.delete_file, signal=signals.post_delete, sender=cls)811 812 def delete_file(self, instance):813 if getattr(instance, self.attname):814 file_name = getattr(instance, 'get_%s_filename' % self.name)()815 # If the file exists and no other object of this type references it,816 # delete it from the filesystem.817 if os.path.exists(file_name) and \818 not instance.__class__._default_manager.filter(**{'%s__exact' % self.name: getattr(instance, self.attname)}):819 os.remove(file_name)820 821 def get_manipulator_field_objs(self):822 return [oldforms.FileUploadField, oldforms.HiddenField]823 824 def get_manipulator_field_names(self, name_prefix):825 return [name_prefix + self.name + '_file', name_prefix + self.name]826 827 def save_file(self, new_data, new_object, original_object, change, rel, save=True):828 upload_field_name = self.get_manipulator_field_names('')[0]829 if new_data.get(upload_field_name, False):830 func = getattr(new_object, 'save_%s_file' % self.name)831 if rel:832 func(new_data[upload_field_name][0]["filename"], new_data[upload_field_name][0]["content"], save)833 else:834 func(new_data[upload_field_name]["filename"], new_data[upload_field_name]["content"], save)835 836 def get_directory_name(self):837 return os.path.normpath(force_unicode(datetime.datetime.now().strftime(smart_str(self.upload_to))))838 839 def get_filename(self, filename):840 from django.utils.text import get_valid_filename841 f = os.path.join(self.get_directory_name(), get_valid_filename(os.path.basename(filename)))842 return os.path.normpath(f)843 844 def save_form_data(self, instance, data):845 from django.newforms.fields import UploadedFile846 if data and isinstance(data, UploadedFile):847 getattr(instance, "save_%s_file" % self.name)(data.filename, data.content, save=False)848 849 def formfield(self, **kwargs):850 defaults = {'form_class': forms.FileField}851 # If a file has been provided previously, then the form doesn't require852 # that a new file is provided this time.853 # The code to mark the form field as not required is used by854 # form_for_instance, but can probably be removed once form_for_instance855 # is gone. ModelForm uses a different method to check for an existing file.856 if 'initial' in kwargs:857 defaults['required'] = False858 defaults.update(kwargs)859 return super(FileField, self).formfield(**defaults)860 861 753 class FilePathField(Field): 862 754 def __init__(self, verbose_name=None, name=None, path='', match=None, recursive=False, **kwargs): 863 755 self.path, self.match, self.recursive = path, match, recursive … … 894 786 defaults.update(kwargs) 895 787 return super(FloatField, self).formfield(**defaults) 896 788 897 class ImageField(FileField):898 def __init__(self, verbose_name=None, name=None, width_field=None, height_field=None, **kwargs):899 self.width_field, self.height_field = width_field, height_field900 FileField.__init__(self, verbose_name, name, **kwargs)901 902 def get_manipulator_field_objs(self):903 return [oldforms.ImageUploadField, oldforms.HiddenField]904 905 def contribute_to_class(self, cls, name):906 super(ImageField, self).contribute_to_class(cls, name)907 # Add get_BLAH_width and get_BLAH_height methods, but only if the908 # image field doesn't have width and height cache fields.909 if not self.width_field:910 setattr(cls, 'get_%s_width' % self.name, curry(cls._get_FIELD_width, field=self))911 if not self.height_field:912 setattr(cls, 'get_%s_height' % self.name, curry(cls._get_FIELD_height, field=self))913 914 def get_internal_type(self):915 return "ImageField"916 917 def save_file(self, new_data, new_object, original_object, change, rel, save=True):918 FileField.save_file(self, new_data, new_object, original_object, change, rel, save)919 # If the image has height and/or width field(s) and they haven't920 # changed, set the width and/or height field(s) back to their original921 # values.922 if change and (self.width_field or self.height_field) and save:923 if self.width_field:924 setattr(new_object, self.width_field, getattr(original_object, self.width_field))925 if self.height_field:926 setattr(new_object, self.height_field, getattr(original_object, self.height_field))927 new_object.save()928 929 def formfield(self, **kwargs):930 defaults = {'form_class': forms.ImageField}931 defaults.update(kwargs)932 return super(ImageField, self).formfield(**defaults)933 934 789 class IntegerField(Field): 935 790 empty_strings_allowed = False 936 791 def get_manipulator_field_objs(self): -
django/db/models/fields/files.py
1 import datetime 2 import os 3 4 from django.conf import settings 5 from django.db.models.fields import Field 6 from django.core.filestorage import storage as default_storage 7 from django.utils.functional import curry 8 from django.dispatch import dispatcher 9 from django.db.models import signals 10 from django.utils.encoding import force_unicode, smart_str 11 from django.utils.translation import ugettext_lazy, ugettext as _ 12 from django import oldforms 13 from django import newforms as forms 14 from django.core import validators 15 16 class File(object): 17 def __init__(self, instance, field, filename): 18 self.instance = instance 19 self.field = field 20 self.storage = field.storage 21 self.filename = filename or u'' 22 23 def __unicode__(self): 24 return self.filename or u'' 25 26 def __repr__(self): 27 return smart_str(u'<%s: %s>' % (self.__class__.__name__, unicode(self) or u'None')) 28 29 def __nonzero__(self): 30 return not not self.filename 31 32 def __eq__(self, other): 33 return self.filename == other 34 35 def path(self): 36 if not self: 37 raise ValueError("The '%s' attribute has no file associated with it." % self.field.name) 38 return self.storage.path(self.filename) 39 40 def url(self): 41 if not self: 42 raise ValueError("The '%s' attribute has no file associated with it." % self.field.name) 43 return self.storage.url(self.filename) 44 45 def filesize(self): 46 if not self: 47 raise ValueError("The '%s' attribute has no file associated with it." % self.field.name) 48 if not hasattr(self, '_filesize'): 49 self._filesize = self.storage.filesize(self.filename) 50 return self._filesize 51 52 def open(self, mode='rb'): 53 if not self: 54 raise ValueError("The '%s' attribute has no file associated with it." % self.field.name) 55 return self.storage.open(self.filename, mode) 56 57 def save(self, filename, raw_contents, save=True): 58 filename = self.field.generate_filename(self.instance, filename) 59 self.filename = self.storage.save(filename, raw_contents) 60 setattr(self.instance, self.field.name, self.filename) 61 self._has_file = True 62 63 # Update the filesize cache 64 self._filesize = len(raw_contents) 65 66 # Save the object because it has changed, unless save is False 67 if save: 68 self.instance.save() 69 70 def delete(self, save=True): 71 if not self: 72 raise ValueError("The '%s' attribute has no file associated with it." % self.field.name) 73 self.storage.delete(self.filename) 74 75 self.filename = None 76 setattr(self.instance, self.field.name, self.filename) 77 78 # Delete the filesize cache 79 if hasattr(self, '_filesize'): 80 del self._filesize 81 82 if save: 83 self.instance.save() 84 85 class FileDescriptor(object): 86 def __init__(self, field): 87 self.field = field 88 89 def __get__(self, instance=None, owner=None): 90 if instance is None: 91 raise AttributeError, "%s can only be accessed from %s instances." % (self.field.name(self.owner.__name__)) 92 return self.field.attr_class(instance, self.field, instance.__dict__[self.field.name]) 93 94 def __set__(self, instance, value): 95 instance.__dict__[self.field.name] = value 96 97 class FileField(Field): 98 attr_class = File 99 100 def __init__(self, verbose_name=None, name=None, upload_to='', storage=None, **kwargs): 101 for arg in ('core', 'primary_key', 'unique'): 102 if arg in kwargs: 103 raise TypeError("__init__() got an unexpected keyword argument '%s'" % arg) 104 105 self.storage = storage or default_storage 106 self.upload_to = upload_to 107 if callable(upload_to): 108 self.generate_filename = upload_to 109 110 kwargs['max_length'] = kwargs.get('max_length', 100) 111 super(FileField, self).__init__(verbose_name, name, **kwargs) 112 113 def get_internal_type(self): 114 return "FileField" 115 116 def get_db_prep_lookup(self, lookup_type, value): 117 if hasattr(value, 'filename'): 118 value = value.filename 119 return super(FileField, self).get_db_prep_lookup(lookup_type, value) 120 121 def get_db_prep_save(self, value): 122 "Returns field's value prepared for saving into a database." 123 # Need to convert UploadedFile objects provided via a form to unicode for database insertion 124 if value is None: 125 return None 126 return unicode(value.filename) 127 128 def get_manipulator_fields(self, opts, manipulator, change, name_prefix='', rel=False, follow=True): 129 field_list = Field.get_manipulator_fields(self, opts, manipulator, change, name_prefix, rel, follow) 130 if not self.blank: 131 if rel: 132 # This validator makes sure FileFields work in a related context. 133 class RequiredFileField(object): 134 def __init__(self, other_field_names, other_file_field_name): 135 self.other_field_names = other_field_names 136 self.other_file_field_name = other_file_field_name 137 self.always_test = True 138 def __call__(self, field_data, all_data): 139 if not all_data.get(self.other_file_field_name, False): 140 c = validators.RequiredIfOtherFieldsGiven(self.other_field_names, ugettext_lazy("This field is required.")) 141 c(field_data, all_data) 142 # First, get the core fields, if any. 143 core_field_names = [] 144 for f in opts.fields: 145 if f.core and f != self: 146 core_field_names.extend(f.get_manipulator_field_names(name_prefix)) 147 # Now, if there are any, add the validator to this FormField. 148 if core_field_names: 149 field_list[0].validator_list.append(RequiredFileField(core_field_names, field_list[1].field_name)) 150 else: 151 v = validators.RequiredIfOtherFieldNotGiven(field_list[1].field_name, ugettext_lazy("This field is required.")) 152 v.always_test = True 153 field_list[0].validator_list.append(v) 154 field_list[0].is_required = field_list[1].is_required = False 155 156 # If the raw path is passed in, validate it's under the MEDIA_ROOT. 157 def isWithinMediaRoot(field_data, all_data): 158 f = os.path.abspath(os.path.join(settings.MEDIA_ROOT, field_data)) 159 if not f.startswith(os.path.abspath(os.path.normpath(settings.MEDIA_ROOT))): 160 raise validators.ValidationError(_("Enter a valid filename.")) 161 field_list[1].validator_list.append(isWithinMediaRoot) 162 return field_list 163 164 def contribute_to_class(self, cls, name): 165 super(FileField, self).contribute_to_class(cls, name) 166 setattr(cls, self.name, FileDescriptor(self)) 167 setattr(cls, 'get_%s_filename' % self.name, curry(cls._get_FIELD_filename, field=self)) 168 setattr(cls, 'get_%s_url' % self.name, curry(cls._get_FIELD_url, field=self)) 169 setattr(cls, 'get_%s_size' % self.name, curry(cls._get_FIELD_size, field=self)) 170 setattr(cls, 'save_%s_file' % self.name, lambda instance, filename, raw_contents, save=True: instance._save_FIELD_file(self, filename, raw_contents, save)) 171 dispatcher.connect(self.delete_file, signal=signals.post_delete, sender=cls) 172 173 def delete_file(self, instance, sender): 174 filename = getattr(instance, self.attname).filename 175 # If no other object of this type references the file, 176 # and it's not the default value for future objects, 177 # delete it from the backend. 178 if filename and filename != self.default and \ 179 not sender._default_manager.filter(**{self.name: filename}): 180 self.storage.delete(filename) 181 182 def get_manipulator_field_objs(self): 183 return [oldforms.FileUploadField, oldforms.HiddenField] 184 185 def get_manipulator_field_names(self, name_prefix): 186 return [name_prefix + self.name + '_file', name_prefix + self.name] 187 188 def save_file(self, new_data, new_object, original_object, change, rel, save=True): 189 upload_field_name = self.get_manipulator_field_names('')[0] 190 if new_data.get(upload_field_name, False): 191 if rel: 192 field = new_data[upload_field_name][0] 193 else: 194 field = new_data[upload_field_name] 195 filename = self.get_filename(field["filename"]) 196 getattr(new_object, self.attname).save(filename, field["content"], save) 197 198 def get_directory_name(self): 199 return os.path.normpath(force_unicode(datetime.datetime.now().strftime(smart_str(self.upload_to)))) 200 201 def get_filename(self, filename): 202 return os.path.normpath(self.storage.get_valid_filename(os.path.basename(filename))) 203 204 def generate_filename(self, instance, filename): 205 return os.path.join(self.get_directory_name(), self.get_filename(filename)) 206 207 def save_form_data(self, instance, data): 208 from django.newforms.fields import UploadedFile 209 if data and isinstance(data, UploadedFile): 210 getattr(instance, self.attname).save(data.filename, data.content, save=False) 211 212 def formfield(self, **kwargs): 213 defaults = {'form_class': forms.FileField} 214 # If a file has been provided previously, then the form doesn't require 215 # that a new file is provided this time. 216 # The code to mark the form field as not required is used by 217 # form_for_instance, but can probably be removed once form_for_instance 218 # is gone. ModelForm uses a different method to check for an existing file. 219 if 'initial' in kwargs: 220 defaults['required'] = False 221 defaults.update(kwargs) 222 return super(FileField, self).formfield(**defaults) 223 224 class ImageFile(File): 225 def get_width(self): 226 return self._get_image_dimensions()[0] 227 228 def get_height(self): 229 return self._get_image_dimensions()[1] 230 231 def _get_image_dimensions(self): 232 if not hasattr(self, '_dimensions_cache'): 233 from django.utils.images import get_image_dimensions 234 self._dimensions_cache = get_image_dimensions(self.open()) 235 return self._dimensions_cache 236 237 def save(self, filename, raw_contents, save=True): 238 super(ImageFile, self).save(filename, raw_contents, save) 239 240 # Update the cache for image dimensions 241 from django.utils.images import get_image_dimensions 242 from cStringIO import StringIO 243 self._dimensions_cache = get_image_dimensions(StringIO(raw_contents)) 244 245 def delete(self, save=True): 246 # Clear the image dimensions cache 247 del self._dimensions_cache 248 249 super(ImageFile, self).delete(save) 250 251 class ImageField(FileField): 252 attr_class = ImageFile 253 254 def __init__(self, verbose_name=None, name=None, width_field=None, height_field=None, **kwargs): 255 self.width_field, self.height_field = width_field, height_field 256 FileField.__init__(self, verbose_name, name, **kwargs) 257 258 def get_manipulator_field_objs(self): 259 return [oldforms.ImageUploadField, oldforms.HiddenField] 260 261 def contribute_to_class(self, cls, name): 262 super(ImageField, self).contribute_to_class(cls, name) 263 # Add get_BLAH_width and get_BLAH_height methods, but only if the 264 # image field doesn't have width and height cache fields. 265 if not self.width_field: 266 setattr(cls, 'get_%s_width' % self.name, curry(cls._get_FIELD_width, field=self)) 267 if not self.height_field: 268 setattr(cls, 'get_%s_height' % self.name, curry(cls._get_FIELD_height, field=self)) 269 270 def get_internal_type(self): 271 return "ImageField" 272 273 def save_file(self, new_data, new_object, original_object, change, rel, save=True): 274 # If the image has height and/or width field(s) and they haven't 275 # changed, set the width and/or height field(s) back to their original 276 # values. 277 if self.width_field or self.height_field: 278 if original_object and not change: 279 if self.width_field: 280 setattr(new_object, self.width_field, getattr(original_object, self.width_field)) 281 if self.height_field: 282 setattr(new_object, self.height_field, getattr(original_object, self.height_field)) 283 else: 284 from cStringIO import StringIO 285 from django.utils.images import get_image_dimensions 286 287 upload_field_name = self.get_manipulator_field_names('')[0] 288 if rel: 289 field = new_data[upload_field_name][0] 290 else: 291 field = new_data[upload_field_name] 292 293 # Get the width and height from the raw content to avoid extra 294 # unnecessary trips to the file backend. 295 width, height = get_image_dimensions(StringIO(field["content"])) 296 297 if self.width_field: 298 setattr(new_object, self.width_field, width) 299 if self.height_field: 300 setattr(new_object, self.height_field, height) 301 FileField.save_file(self, new_data, new_object, original_object, change, rel, save) 302 303 def formfield(self, **kwargs): 304 defaults = {'form_class': forms.ImageField} 305 defaults.update(kwargs) 306 return super(ImageField, self).formfield(**defaults) -
django/db/models/manipulators.py
1 1 from django.core.exceptions import ObjectDoesNotExist 2 2 from django import oldforms 3 3 from django.core import validators 4 from django.db.models.fields import FileField, AutoField 4 from django.db.models.fields import AutoField 5 from django.db.models.fields.files import FileField 5 6 from django.dispatch import dispatcher 6 7 from django.db.models import signals 7 8 from django.utils.functional import curry -
django/utils/images.py
6 6 7 7 import ImageFile 8 8 9 def get_image_dimensions( path):10 """Returns the (width, height) of an image at a givenpath."""9 def get_image_dimensions(file_or_path): 10 """Returns the (width, height) of an image, given an open file or a path.""" 11 11 p = ImageFile.Parser() 12 fp = open(path, 'rb') 12 if hasattr(file_or_path, 'read'): 13 fp = file_or_path 14 else: 15 fp = open(file_or_path, 'rb') 13 16 while 1: 14 17 data = fp.read(1024) 15 18 if not data: -
docs/custom_model_fields.txt
580 580 instance, not a ``HandField``). So if your ``__unicode__()`` method 581 581 automatically converts to the string form of your Python object, you can 582 582 save yourself a lot of work. 583 584 Writing a ``FileField`` subclass 585 ================================= 586 587 In addition to the above methods, fields that deal with files have a few other 588 special requirements which must be taken into account. The majority of the 589 mechanics provided by ``FileField``, such as controlling database storage and 590 retrieval, can remain unchanged, leaving subclasses to deal with the challenge 591 of supporting a particular type of file. 592 593 Django provides a ``File`` class, which is used as a proxy to the file's 594 contents and operations. This can be subclassed to customzie hwo the file is 595 accessed, and what methods are available. It lives at 596 ``django.db.models.fields.files``, and its default behavior is explained in the 597 `file documentation`_. 598 599 Once a subclass of ``File`` is created, the new ``FileField`` subclass must be 600 told to use it. To do so, simply assign the new ``File`` subclass to the special 601 ``attr_class`` attribute of the ``FileField`` subclass. 602 603 .. _file documentation: ../files/ 604 605 A few suggestions 606 ------------------ 607 608 In addition to the above details, there are a few guidelines which can greatly 609 improve the efficiency and readability of the field's code. 610 611 1. The source for Django's own ``ImageField`` (in 612 ``django/db/models/fields/files.py``) is a great example of how to 613 subclass ``FileField`` to support a particular type of file, as it 614 incorporates all of the techniques described above. 615 616 2. Cache file attributes wherever possible. Since files may be stored in 617 remote storage systems, retrieving them may cost extra time, or even 618 money, that isn't always necessary. Once a file is retrieved to obtain 619 some data about its content, cache as much of that data as possible to 620 reduce the number of times the file must be retrieved on subsequent 621 calls for that information. -
docs/db-api.txt
2198 2198 get_FOO_filename() 2199 2199 ------------------ 2200 2200 2201 **Deprecated in Django development version. See `managing files`_ for the new, 2202 preferred method for dealing with files.** 2203 2201 2204 For every ``FileField``, the object will have a ``get_FOO_filename()`` method, 2202 2205 where ``FOO`` is the name of the field. This returns the full filesystem path 2203 2206 to the file, according to your ``MEDIA_ROOT`` setting. … … 2208 2211 get_FOO_url() 2209 2212 ------------- 2210 2213 2214 **Deprecated in Django development version. See `managing files`_ for the new, 2215 preferred method for dealing with files.** 2216 2211 2217 For every ``FileField``, the object will have a ``get_FOO_url()`` method, 2212 2218 where ``FOO`` is the name of the field. This returns the full URL to the file, 2213 2219 according to your ``MEDIA_URL`` setting. If the value is blank, this method … … 2216 2222 get_FOO_size() 2217 2223 -------------- 2218 2224 2225 **Deprecated in Django development version. See `managing files`_ for the new, 2226 preferred method for dealing with files.** 2227 2219 2228 For every ``FileField``, the object will have a ``get_FOO_size()`` method, 2220 2229 where ``FOO`` is the name of the field. This returns the size of the file, in 2221 2230 bytes. (Behind the scenes, it uses ``os.path.getsize``.) … … 2223 2232 save_FOO_file(filename, raw_contents) 2224 2233 ------------------------------------- 2225 2234 2235 **Deprecated in Django development version. See `managing files`_ for the new, 2236 preferred method for dealing with files.** 2237 2226 2238 For every ``FileField``, the object will have a ``save_FOO_file()`` method, 2227 2239 where ``FOO`` is the name of the field. This saves the given file to the 2228 2240 filesystem, using the given filename. If a file with the given filename already … … 2232 2244 get_FOO_height() and get_FOO_width() 2233 2245 ------------------------------------ 2234 2246 2247 **Deprecated in Django development version. See `managing files`_ for the new, 2248 preferred method for dealing with files.** 2249 2235 2250 For every ``ImageField``, the object will have ``get_FOO_height()`` and 2236 2251 ``get_FOO_width()`` methods, where ``FOO`` is the name of the field. This 2237 2252 returns the height (or width) of the image, as an integer, in pixels. 2238 2253 2254 .. _`managing files`: ../files/ 2255 2239 2256 Shortcuts 2240 2257 ========= 2241 2258 -
docs/files.txt
1 ============== 2 Managing files 3 ============== 4 5 **New in Django development version** 6 7 When dealing with files, Django provides a number of features to make this task 8 easier and more portable. A storage protocol is available to allow files to be 9 stored in a variety of locations, and a special object is provided to allow 10 models to make use of this protocol, without having to worry about which storage 11 system is being used. 12 13 Using files in models 14 ===================== 15 16 When accessing a ``FileField`` attached to a model, a special object provides 17 access to the file and information about it. 18 19 Example 20 ------- 21 22 Consider the following model, using an ``ImageField`` to store a product photo:: 23 24 class Product(models.Model): 25 name = models.CharField(maxlength=255) 26 price = models.DecimalField(max_digits=5, decimal_places=2) 27 photo = models.ImageField(upload_to='product_photos') 28 29 Your views can then use the ``photo`` attribute with the functions described 30 above, as follows:: 31 32 >>> car = Product.object.get(name="'57 Chevy") 33 >>> car.photo 34 <ImageFile: 123.jpg> 35 >>> car.photo.url() 36 '/products/photo/123.jpg' 37 >>> car.photo.width(), car.photo.height() 38 (800, 600) 39 40 ``path()`` 41 ---------- 42 43 Returns the absolute path to the file's location on a local filesystem. For 44 storage systems which do not store files locally, this will return `None`. 45 46 ``url()`` 47 --------- 48 49 Provides a URL where the content of the file can be retrieved. Therefore, 50 returned from this method is suitable for use as the destination of a link to 51 the file. 52 53 ``filesize()`` 54 -------------- 55 56 Returns the size of the file, as an integer. 57 58 ``open(mode='rb')`` 59 ------------------- 60 61 Returns an open file object, providing read or write access to the file's 62 contents. The ``mode`` argument allows the same values as Python's standard 63 ``open()`` function. 64 65 ``save(filename, raw_contents, save=True)`` 66 ------------------------------------------- 67 68 Saves a new file with the filename and contents provided. This will not replace 69 the existing file, but will create a new file and update the object to point to 70 it. The optional ``save`` argument dictates whether the model instance will be 71 saved to the database immediately. 72 73 ``width() and height()`` 74 ------------------------ 75 76 When using an ``ImageField``, these two methods will be available, providing 77 easy access to the dimensions of the image. 78 79 Using a storage system with FileField 80 ===================================== 81 82 When using a storage system, supply whatever options are appropriate for 83 that system when creating a new object. Then pass that object as the ``storage`` 84 argument to a ``FileField``. Details on the requirements for the included 85 storage system can be found below. 86 87 If using the default storage system, it is not necessary to create a storage 88 object explicitly. In this case, the ``FileField`` will use the one referenced 89 by the `DEFAULT_FILE_STORAGE setting`_. 90 91 See the ```FileField`` documentation`_ for more information on using the field. 92 93 .. _DEFAULT_FILE_STORAGE setting: ../settings/#default-file-storage 94 .. _FileField documentation: ../model-api/#filefield 95 96 For example, the following code will explicitly use the ``FileSystemStorage``:: 97 98 from django.db import models 99 from django.core.filestorage.filesystem import FileSystemStorage 100 101 fs = FileSystemStorage(location='product_photos') 102 103 class Product(models.Model): 104 name = models.CharField(maxlength=255) 105 price = models.DecimalField(max_digits=5, decimal_places=2) 106 photo = models.ImageField(storage=fs) 107 108 Using a storage system on its own 109 ================================= 110 111 Storage systems may also be used directly, without being attached to a model. 112 Simply use the following API on any instantiated storage system to access files 113 without having to worry about the underlying mechanism. 114 115 In addition to explicit storage mechanisms, the file storage module, 116 ``django.core.filestorage``, exports a ``storage`` object that's automatically 117 created from the ``DEFAULT_FILE_STORAGE`` setting:: 118 119 >>> from django.core.filestorage import storage 120 121 With a functional storage system on hand, managing files is quite simple, with a 122 few basic methods to handle the most common operations:: 123 124 >>> path = storage.save('/path/to/file', 'new content') 125 >>> path 126 u'/path/to/file' 127 >>> storage.filesize(path) 128 11 129 >>> storage.open(path).read() 130 'new content' 131 >>> storage.delete(path) 132 >>> storage.exists(path) 133 False 134 135 ``exists(filename)`` 136 -------------------- 137 138 Returns ``True`` or ``False, indicating whether there is already a file present 139 at the location referenced by``filename``. 140 141 ``open(filename, mode='rb')`` 142 ----------------------------- 143 144 Returns an open file, or file-like, object to provide access to the contents of 145 the file referenced by ``filename``. The ``mode`` argument allows the same 146 values as Python's standard ``open()`` function. 147 148 ``filesize(filename)`` 149 ---------------------- 150 151 Returns the total size of the file referenced by ``filename``, as an integer. 152 153 ``url(filename)`` 154 ----------------- 155 156 Returns the URL where the contents of the file referenced by ``filename`` can 157 be accessed. 158 159 ``save(filename, raw_contents)`` 160 -------------------------------- 161 162 Saves a new file using the storage system, preferably with the name specified. 163 If there already exists a file at the location referenced by ``filename``, this 164 may modify the filename as necessary to locate one that is available. Once the 165 file is saved, this method will return the filename where the file was actually 166 stored. 167 168 ``delete(filename)`` 169 -------------------- 170 171 Deletes the file referenced by ``filename``. If the file does not already exist, 172 this method will simply return without raising an exception. 173 174 Available storage systems 175 ========================= 176 177 Only one storage system is supplied in the official Django distribution, but 178 more may be available elsewhere. If you'd like to use a different storage system 179 than the one listed below, see the documentation included with it. 180 181 ``django.core.filestorage.filesystem.FileSystemStorage`` 182 -------------------------------------------------------- 183 184 This simply stores files on the system's standard filesystem. 185 186 ====================== =================================================== 187 Argument Description 188 ====================== =================================================== 189 ``location`` Optional. Absolute path to the directory that will 190 hold the files. If omitted, it will be set to the 191 value of your ``MEDIA_ROOT`` setting. 192 ``base_url`` Optional. URL that serves the files stored at this 193 location. If omitted, it will default to the value 194 of your ``MEDIA_URL`` setting. 195 ====================== =================================================== 196 197 Writing a storage system 198 ======================== 199 200 While the default filesystem storage is suitable for most needs, there are many 201 other storage mechanisms that may be used, and situations that will require 202 special processing. In order to use Django in these environments, it's fairly 203 simple to write a new storage system, creating a wrapper around whatever 204 libraries are used to access your files, or simply customizing method calls on 205 an existing storage class. 206 207 If a storage system requires any configuration options to determine how it 208 should access the underlying storage mechanism or cusotmize its behavior in 209 other ways, those options should be specified in a particular way. Because the 210 default storage system is specified as a string, Django must be able to 211 instantiate it without any arguments, and any required arguments should be 212 specified as global settings, which can be referenced from the storage system. 213 For example:: 214 215 from django.conf import settings 216 from django.core.filestorage.base import Storage 217 218 class CustomStorage(Storage): 219 def __init__(self, option=settings.CUSTOM_STORAGE_OPTION): 220 ... 221 222 All storage systems must implement the methods described above, but Django also 223 uses two other methods to assist in the process. When writing a custom class, 224 these methods may be inherited from the built-in ``Storage`` class, living at 225 ``django.core.filestorage.base``. When extending an existing storage class, they 226 can be overriden to allow a great deal of customization. 227 228 ``get_valid_filename(filename)`` 229 -------------------------------- 230 231 Returns a filename suitable for use with the underlying storage system. The 232 ``filename`` argument passed to this method is the original filename sent to the 233 server, after having any path information removed. Override this to customize 234 how non-standard characters are converted to safe filenames. 235 236 The code provided on ``Storage`` retains only alpha-numeric characters, periods 237 and underscores from the original filename, removing everything else. 238 239 ``get_available_filename(filename)`` 240 ------------------------------------ 241 242 Returns a filename that is available in the storage mechanism, possibly taking 243 the provided filename into account. The ``filename`` argument passed to this 244 method will have already cleaned to a filename valid for the storage system, 245 according to the ``get_valid_filename()`` method described above. 246 247 The code provided on ``Storage`` simply appends underscores to the filename 248 until it finds one that's available in the destination directory. 249 250 Opening remote files 251 -------------------- 252 253 When accessing a file stored at a remote location, the object returned by 254 ``open()`` should function like a standard `file object`_, but to keep 255 network traffic to a minimum, writes to the remote storage system should only 256 occur if actually necessary. To make this task easier, Django provides a class 257 to automate this process. 258 259 Living at ``django.core.filestorage.base``, the ``RemoteFile`` class simulates 260 a standard Python `file object`_, but can write changes to a remote storage 261 system when application using a function provided by the storage system. 262 Creating an instance of this object requires three arguments, which are 263 described below. 264 265 ====================== =================================================== 266 Argument Description 267 ====================== =================================================== 268 ``data`` The raw content of the file. 269 ``mode`` The access mode that was passed to the ``open()`` 270 method. 271 ``writer`` A function that will be used to write the contents 272 to the underlying storage mechanism. The function 273 provided here will need to take a single argument, 274 which will be the raw content to be written to the 275 file. 276 ====================== =================================================== 277 278 .. _file object: http://docs.python.org/lib/bltin-file-objects.html 279 -
docs/model-api.txt
230 230 ``FileField`` 231 231 ~~~~~~~~~~~~~ 232 232 233 A file-upload field. Has one **required** argument: 233 A file-upload field. Has two special arguments, of which the first is 234 **required**: 234 235 235 236 ====================== =================================================== 236 237 Argument Description 237 238 ====================== =================================================== 238 ``upload_to`` A local filesystem path that will be appended to 239 your ``MEDIA_ROOT`` setting to determine the 240 output of the ``get_<fieldname>_url()`` helper 241 function. 239 ``upload_to`` Required. A filesystem-style path that will be 240 prepended to the filename before being committed to 241 the final storage destination. 242 243 **New in Django development version** 244 245 This may also be a callable, such as a function, 246 which will be called to obtain the upload path, 247 including the filename. See below for details. 248 249 ``storage`` **New in Django development version** 250 251 Optional. A storage object, which handles the 252 storage and retrieval of your files. See `managing 253 files`_ for details on how to provide this object. 242 254 ====================== =================================================== 243 255 244 This path may contain `strftime formatting`_, which will be replaced by the 245 date/time of the file upload (so that uploaded files don't fill up the given 246 directory). 256 .. _managing files: ../files/ 247 257 258 The ``upload_to`` path may contain `strftime formatting`_, which will be 259 replaced by the date/time of the file upload (so that uploaded files don't fill 260 up the given directory). 261 262 **New in Django development version** 263 264 If a callable is provided for the ``upload_to`` argument, that callable must be 265 able to accept two arguments, and return a Unix-style path (with forward 266 slashes) to be passed along to the storage system. The two arguments that will 267 be passed are: 268 269 ====================== =================================================== 270 Argument Description 271 ====================== =================================================== 272 ``instance`` An instance of the model where the ``FileField`` is 273 defined. More specifically, this is the particular 274 instance where the current file is being attached. 275 276 **Note**: In most cases, this object will not have 277 been saved to the database yet, so if it uses the 278 default ``AutoField``, *it might not yet have a 279 value for its primary key field*. 280 281 ``filename`` The filename that was originally given to the file. 282 This may or may not be taken into account when 283 determining the final destination path. 284 ====================== =================================================== 285 248 286 The admin represents this field as an ``<input type="file">`` (a file-upload 249 287 widget). 250 288 251 Using a ``FileField`` or an ``ImageField`` (see below) in a model takes a few252 s teps:289 Using a ``FileField`` or an ``ImageField`` (see below) in a model without a 290 specified storage system takes a few steps: 253 291 254 292 1. In your settings file, you'll need to define ``MEDIA_ROOT`` as the 255 293 full path to a directory where you'd like Django to store uploaded -
docs/settings.txt
409 409 isn't manually specified. Used with ``DEFAULT_CHARSET`` to construct the 410 410 ``Content-Type`` header. 411 411 412 DEFAULT_FILE_STORAGE 413 -------------------- 414 415 Default: ``'django.core.filestorage.filesystem.FileSystemStorage'`` 416 417 Default file storage class to be used for any file-related operations that don't 418 specify a particular storage system. See the `file documentation`_ for details. 419 420 .. _file documentation: ../files/ 421 412 422 DEFAULT_FROM_EMAIL 413 423 ------------------ 414 424 -
tests/modeltests/files/__init__.py
Property changes on: tests/modeltests/files ___________________________________________________________________ Name: svn:ignore + *.pyc
1 -
tests/modeltests/files/models.py
1 """ 2 42. Storing files according to a custom storage system 3 4 FileField and its variations can take a "storage" argument to specify how and 5 where files should be stored. 6 """ 7 8 import tempfile 9 10 from django.db import models 11 from django.core.filestorage.filesystem import FileSystemStorage 12 from django.core.cache import cache 13 14 temp_dir = tempfile.gettempdir() 15 16 temp_storage = FileSystemStorage(location=temp_dir) 17 18 # Write out a file to be used as default content 19 temp_storage.save('tests/default.txt', 'default_content') 20 open('%s/tests/default.txt' % temp_dir, 'w').write('default content') 21 22 class Storage(models.Model): 23 def custom_upload_to(self, filename): 24 return 'foo' 25 26 normal = models.FileField(storage=temp_storage, upload_to='tests') 27 custom = models.FileField(storage=temp_storage, upload_to=custom_upload_to) 28 default = models.FileField(storage=temp_storage, upload_to='tests', default='tests/default.txt') 29 30 __test__ = {'API_TESTS':""" 31 # An object without a file has limited functionality 32 33 >>> obj1 = Storage() 34 >>> obj1.normal 35 <File: None> 36 >>> obj1.normal.filesize() 37 Traceback (most recent call last): 38 ... 39 ValueError: The 'normal' attribute has no file associated with it. 40 41 # Saving a file enables full functionality 42 43 >>> obj1.normal.save('django_test.txt', 'content') 44 >>> obj1.normal 45 <File: tests/django_test.txt> 46 >>> obj1.normal.filesize() 47 7 48 >>> obj1.normal.open().read() 49 'content' 50 51 # Save another file with the same name 52 53 >>> obj2 = Storage() 54 >>> obj2.normal.save('django_test.txt', 'more content') 55 >>> obj2.normal 56 <File: tests/django_test_.txt> 57 >>> obj2.normal.filesize() 58 12 59 60 # Push the objects into the cache to make sure they pickle properly 61 62 >>> cache.set('obj1', obj1) 63 >>> cache.set('obj2', obj2) 64 >>> cache.get('obj2').normal 65 <File: tests/django_test_.txt> 66 67 # Deleting an object deletes the file it uses, if there are no other objects 68 # still using that file 69 70 >>> obj2.delete() 71 >>> obj2.normal.save('django_test.txt', 'more content') 72 >>> obj2.normal 73 <File: tests/django_test_.txt> 74 75 # Default values allow an object to access a single file 76 77 >>> obj3 = Storage.objects.create() 78 >>> obj3.default 79 <File: tests/default.txt> 80 >>> obj3.default.open().read() 81 'default content' 82 83 # But it shouldn't be deleted, even if there are no more objects using it 84 85 >>> obj3.delete() 86 >>> obj3 = Storage() 87 >>> obj3.default.open().read() 88 'default content' 89 90 # Clean up the temporary files 91 92 >>> obj1.normal.delete() 93 >>> obj2.normal.delete() 94 >>> obj3.default.delete() 95 """} -
tests/modeltests/model_forms/models.py
11 11 import tempfile 12 12 13 13 from django.db import models 14 from django.core.filestorage.filesystem import FileSystemStorage 14 15 16 temp_storage = FileSystemStorage(tempfile.gettempdir()) 17 15 18 ARTICLE_STATUS = ( 16 19 (1, 'Draft'), 17 20 (2, 'Pending'), … … 60 63 61 64 class TextFile(models.Model): 62 65 description = models.CharField(max_length=20) 63 file = models.FileField( upload_to=tempfile.gettempdir())66 file = models.FileField(storage=temp_storage, upload_to='tests') 64 67 65 68 def __unicode__(self): 66 69 return self.description 67 70 68 71 class ImageFile(models.Model): 69 72 description = models.CharField(max_length=20) 70 image = models.FileField( upload_to=tempfile.gettempdir())73 image = models.FileField(storage=temp_storage, upload_to='tests') 71 74 72 75 def __unicode__(self): 73 76 return self.description … … 799 802 <class 'django.newforms.fields.UploadedFile'> 800 803 >>> instance = f.save() 801 804 >>> instance.file 802 u'...test1.txt' 805 <File: .../test1.txt> 803 806 804 807 # Edit an instance that already has the file defined in the model. This will not 805 808 # save the file again, but leave it exactly as it is. … … 808 811 >>> f.is_valid() 809 812 True 810 813 >>> f.cleaned_data['file'] 811 u'...test1.txt' 814 <File: .../test1.txt> 812 815 >>> instance = f.save() 813 816 >>> instance.file 814 u'...test1.txt' 817 <File: .../test1.txt> 815 818 816 819 # Delete the current file since this is not done by Django. 817 820 818 >>> os.unlink(instance.get_file_filename())821 >>> instance.file.delete() 819 822 820 823 # Override the file by uploading a new one. 821 824 … … 824 827 True 825 828 >>> instance = f.save() 826 829 >>> instance.file 827 u'...test2.txt' 830 <File: .../test2.txt> 828 831 829 832 >>> instance.delete() 830 833 … … 836 839 True 837 840 >>> instance = f.save() 838 841 >>> instance.file 839 '' 842 <File: None> 840 843 841 844 >>> f = TextFileForm(data={'description': u'Assistance'}, files={'file': {'filename': 'test3.txt', 'content': 'hello world'}}, instance=instance) 842 845 >>> f.is_valid() 843 846 True 844 847 >>> instance = f.save() 845 848 >>> instance.file 846 u'...test3.txt' 849 <File: .../test3.txt> 847 850 >>> instance.delete() 848 851 849 852 # ImageField ################################################################### … … 865 868 <class 'django.newforms.fields.UploadedFile'> 866 869 >>> instance = f.save() 867 870 >>> instance.image 868 u'...test.png' 871 <File: .../test.png> 869 872 870 873 # Edit an instance that already has the image defined in the model. This will not 871 874 # save the image again, but leave it exactly as it is. … … 874 877 >>> f.is_valid() 875 878 True 876 879 >>> f.cleaned_data['image'] 877 u'...test.png' 880 <File: .../test.png> 878 881 >>> instance = f.save() 879 882 >>> instance.image 880 u'...test.png' 883 <File: .../test.png> 881 884 882 885 # Delete the current image since this is not done by Django. 883 886 884 >>> os.unlink(instance.get_image_filename())887 >>> instance.image.delete() 885 888 886 889 # Override the file by uploading a new one. 887 890 … … 890 893 True 891 894 >>> instance = f.save() 892 895 >>> instance.image 893 u'...test2.png' 896 <File: .../test2.png> 894 897 895 898 >>> instance.delete() 896 899 … … 902 905 True 903 906 >>> instance = f.save() 904 907 >>> instance.image 905 '' 908 <File: None> 906 909 907 910 >>> f = ImageFileForm(data={'description': u'And a final one'}, files={'image': {'filename': 'test3.png', 'content': image_data}}, instance=instance) 908 911 >>> f.is_valid() 909 912 True 910 913 >>> instance = f.save() 911 914 >>> instance.image 912 u'...test3.png' 915 <File: .../test3.png> 913 916 >>> instance.delete() 914 917 915 918 """} -
tests/regressiontests/bug639/models.py
1 1 import tempfile 2 2 3 from django.db import models 4 from django.core.filestorage.filesystem import FileSystemStorage 3 5 6 temp_storage = FileSystemStorage(tempfile.gettempdir()) 7 4 8 class Photo(models.Model): 5 9 title = models.CharField(max_length=30) 6 image = models.FileField( upload_to=tempfile.gettempdir())10 image = models.FileField(storage=temp_storage, upload_to='tests') 7 11 8 12 # Support code for the tests; this keeps track of how many times save() gets 9 13 # called on each instance. 10 14 def __init__(self, *args, **kwargs): 11 super(Photo, self).__init__(*args, **kwargs)12 self._savecount = 015 super(Photo, self).__init__(*args, **kwargs) 16 self._savecount = 0 13 17 14 18 def save(self): 15 19 super(Photo, self).save() 16 self._savecount += 117 No newline at end of file 20 self._savecount += 1 21 No newline at end of file -
tests/regressiontests/bug639/tests.py
39 39 Make sure to delete the "uploaded" file to avoid clogging /tmp. 40 40 """ 41 41 p = Photo.objects.get() 42 os.unlink(p.get_image_filename()) 43 No newline at end of file 42 p.image.delete(save=False) -
tests/regressiontests/serializers_regress/models.py
157 157 class EmailPKData(models.Model): 158 158 data = models.EmailField(primary_key=True) 159 159 160 class FilePKData(models.Model):161 data = models.FileField(primary_key=True, upload_to='/foo/bar')160 # class FilePKData(models.Model): 161 # data = models.FileField(primary_key=True, upload_to='/foo/bar') 162 162 163 163 class FilePathPKData(models.Model): 164 164 data = models.FilePathField(primary_key=True) -
tests/regressiontests/serializers_regress/tests.py
125 125 (data_obj, 41, EmailData, None), 126 126 (data_obj, 42, EmailData, ""), 127 127 (data_obj, 50, FileData, 'file:///foo/bar/whiz.txt'), 128 (data_obj, 51, FileData, None),128 # (data_obj, 51, FileData, None), 129 129 (data_obj, 52, FileData, ""), 130 130 (data_obj, 60, FilePathData, "/foo/bar/whiz.txt"), 131 131 (data_obj, 61, FilePathData, None), … … 223 223 # (pk_obj, 620, DatePKData, datetime.date(2006,6,16)), 224 224 # (pk_obj, 630, DateTimePKData, datetime.datetime(2006,6,16,10,42,37)), 225 225 (pk_obj, 640, EmailPKData, "hovercraft@example.com"), 226 (pk_obj, 650, FilePKData, 'file:///foo/bar/whiz.txt'),226 # (pk_obj, 650, FilePKData, 'file:///foo/bar/whiz.txt'), 227 227 (pk_obj, 660, FilePathPKData, "/foo/bar/whiz.txt"), 228 228 (pk_obj, 670, DecimalPKData, decimal.Decimal('12.345')), 229 229 (pk_obj, 671, DecimalPKData, decimal.Decimal('-12.345')), -
tests/regressiontests/storage/__init__.py
Property changes on: tests/regressiontests/storage ___________________________________________________________________ Name: svn:ignore + *.pyc
1 -
tests/regressiontests/storage/models.py
1 # Empty file to force tests to run 2 No newline at end of file -
tests/regressiontests/storage/tests.py
1 """ 2 Tests for the file storage mechanism 3 4 >>> import tempfile 5 >>> from django.core.filestorage.filesystem import FileSystemStorage 6 7 # Instantiate a storage system manually, specifying a location. 8 9 >>> temp_storage = FileSystemStorage(tempfile.gettempdir()) 10 11 # Standard file access options are available, and work as expected. 12 13 >>> temp_storage.exists('storage_test') 14 False 15 >>> file = temp_storage.open('storage_test', 'w') 16 >>> file.write('storage contents') 17 >>> file.close() 18 19 >>> temp_storage.exists('storage_test') 20 True 21 >>> file = temp_storage.open('storage_test', 'r') 22 >>> file.read() 23 'storage contents' 24 >>> file.close() 25 26 >>> temp_storage.delete('storage_test') 27 >>> temp_storage.exists('storage_test') 28 False 29 30 # Files can only be accessed if they're below the specified location. 31 32 >>> temp_storage.exists('..') 33 Traceback (most recent call last): 34 ... 35 SuspiciousOperation: Attempted access to '..' denied. 36 >>> temp_storage.open('/etc/passwd') 37 Traceback (most recent call last): 38 ... 39 SuspiciousOperation: Attempted access to '/etc/passwd' denied. 40 41 # RemoteFile allows files to be committed by way of a user-defined function. 42 43 >>> from django.core.filestorage.base import RemoteFile 44 >>> def write_file(contents): 45 ... print 'Writing %s' % contents 46 47 # Opening for read access doesn't commit back to the server 48 49 >>> file = RemoteFile('', 'r', write_file) 50 >>> file.close() 51 52 # The same goes for opening for write access, but not actually writing 53 54 >>> file = RemoteFile('', 'w', write_file) 55 >>> file.close() 56 57 # But once it's written to, it gets committed on close 58 59 >>> file = RemoteFile('', 'w', write_file) 60 >>> file.write('remote contents') # Content isn't committed yet 61 >>> file.close() # Content gets committed to the storage system 62 Writing remote contents 63 64 # Custom storage systems can be created to customize behavior 65 66 >>> class CustomStorage(FileSystemStorage): 67 ... def get_available_filename(self, filename): 68 ... # Append numbers to duplicate files rather than underscores, like Trac 69 ... 70 ... parts = filename.split('.') 71 ... basename, ext = parts[0], parts[1:] 72 ... number = 2 73 ... 74 ... while self.exists(filename): 75 ... filename = '.'.join([basename, str(number)] + ext) 76 ... number += 1 77 ... 78 ... return filename 79 >>> custom_storage = CustomStorage(tempfile.gettempdir()) 80 81 >>> first = custom_storage.save('custom_storage', 'custom contents') 82 >>> first 83 u'custom_storage' 84 >>> second = custom_storage.save('custom_storage', 'more contents') 85 >>> second 86 u'custom_storage.2' 87 >>> custom_storage.delete(first) 88 >>> custom_storage.delete(second) 89 """ 90 No newline at end of file