Ticket #5361: 5361-r8012.diff
File 5361-r8012.diff, 69.5 KB (added by , 16 years ago) |
---|
-
django/conf/global_settings.py
223 223 # Path to the "jing" executable -- needed to validate XMLFields 224 224 JING_PATH = "/usr/bin/jing" 225 225 226 # Default file storage mechanism that holds media. 227 DEFAULT_FILE_STORAGE = 'django.core.files.storage.FileSystemStorage' 228 226 229 # Absolute path to the directory that holds media. 227 230 # Example: "/home/media/media.lawrence.com/" 228 231 MEDIA_ROOT = '' -
django/core/files/__init__.py
1 import os 2 3 from django.core.files.base import File 4 5 def open(path, mode='rb', storage=None, mixin=None): 6 """ 7 A more intelligent open() than the one that comes with Python, working with 8 various storage systems and providing a more fully-featured File object. 9 """ 10 if storage is None: 11 # In keeping Python's own open(), if no storage system is supplied, it 12 # looks in the current directory. Since FileSystemStorage protects from 13 # access outside of its base location, though, this will prevent access 14 # to arbitrary file paths. 15 from django.core.files.storage import FileSystemStorage 16 if os.path.abspath(path) == path: 17 # If an absolute path was given, the storage system needs to 18 # set to the root of the filesystem 19 location = path.split(os.path.sep)[0] + os.path.sep 20 storage = FileSystemStorage(location=location) 21 else: 22 storage = FileSystemStorage(location='') 23 return storage.open(path, mode, mixin=mixin) -
django/core/files/base.py
1 import os 2 3 try: 4 from cStringIO import StringIO 5 except ImportError: 6 from StringIO import StringIO 7 8 class File(object): 9 DEFAULT_CHUNK_SIZE = 64 * 2**10 10 11 def __init__(self, file): 12 self.file = file 13 self.name = file.name 14 self.mode = file.mode 15 self.closed = False 16 17 def __str__(self): 18 return str(self.name or '') 19 20 def __unicode__(self): 21 return unicode(str(self)) 22 23 def __repr__(self): 24 return "<%s: %s>" % (self.__class__.__name__, self or "None") 25 26 def __nonzero__(self): 27 return not not self.name 28 29 def __len__(self): 30 return self.size 31 32 def _get_size(self): 33 if not hasattr(self, '_size'): 34 if hasattr(self.file, 'size'): 35 self._size = self.file.size 36 elif os.path.exists(self.file.name): 37 self._size = os.path.getsize(self.file.name) 38 else: 39 raise AttributeError("Unable to determine the file's size.") 40 return self._size 41 42 def _set_size(self, size): 43 self._size = size 44 45 size = property(_get_size, _set_size) 46 47 def chunks(self, chunk_size=None): 48 """ 49 Read the file and yield chucks of ``chunk_size`` bytes (defaults to 50 ``UploadedFile.DEFAULT_CHUNK_SIZE``). 51 """ 52 if not chunk_size: 53 chunk_size = self.__class__.DEFAULT_CHUNK_SIZE 54 55 if hasattr(self, 'seek'): 56 self.seek(0) 57 # Assume the pointer is at zero... 58 counter = self.size 59 60 while counter > 0: 61 yield self.read(chunk_size) 62 counter -= chunk_size 63 64 def multiple_chunks(self, chunk_size=None): 65 """ 66 Returns ``True`` if you can expect multiple chunks. 67 68 NB: If a particular file representation is in memory, subclasses should 69 always return ``False`` -- there's no good reason to read from memory in 70 chunks. 71 """ 72 if not chunk_size: 73 chunk_size = UploadedFile.DEFAULT_CHUNK_SIZE 74 return self.size > chunk_size 75 76 def xreadlines(self): 77 return iter(self) 78 79 def readlines(self): 80 return list(self.xreadlines()) 81 82 def __iter__(self): 83 # Iterate over this file-like object by newlines 84 buffer_ = None 85 for chunk in self.chunks(): 86 chunk_buffer = StringIO(chunk) 87 88 for line in chunk_buffer: 89 if buffer_: 90 line = buffer_ + line 91 buffer_ = None 92 93 # If this is the end of a line, yield 94 # otherwise, wait for the next round 95 if line[-1] in ('\n', '\r'): 96 yield line 97 else: 98 buffer_ = line 99 100 if buffer_ is not None: 101 yield buffer_ 102 103 def open(self, mode=None): 104 if not self.closed: 105 self.seek(0) 106 elif os.path.exists(self.file.name): 107 self.file = open(self.file.name, self.file.mode) 108 else: 109 raise ValueError("The file cannot be reopened.") 110 111 def seek(self, position): 112 self.file.seek(position) 113 114 def tell(self): 115 return self.file.tell() 116 117 def read(self, num_bytes=None): 118 if num_bytes is None: 119 return self.file.read() 120 return self.file.read(num_bytes) 121 122 def write(self, content): 123 if not self.mode.startswith('w'): 124 raise IOError("File was not opened with write access.") 125 self.file.write(content) 126 127 def close(self): 128 self.file.close() 129 self.closed = True 130 131 class ContentFile(File): 132 """ 133 A File-like object that takes just raw content, rather than an actual file. 134 """ 135 def __init__(self, content): 136 self.file = StringIO(content or '') 137 self.size = len(content or '') 138 self.file.seek(0) 139 self.closed = False 140 141 def __str__(self): 142 return 'Raw content' 143 144 def __nonzero__(self): 145 return True 146 147 def open(self, mode=None): 148 if self.closed: 149 self.closed = False 150 self.seek(0) -
django/core/files/images.py
1 """ 2 Utility functions for handling images. 3 4 Requires PIL, as you might imagine. 5 """ 6 7 from PIL import ImageFile as PIL 8 from django.core.files import File 9 10 class ImageFile(File): 11 """ 12 A mixin for use alongside django.core.files.base.File, which provides 13 additional features for dealing with images. 14 """ 15 def _get_width(self): 16 return self._get_image_dimensions()[0] 17 width = property(_get_width) 18 19 def _get_height(self): 20 return self._get_image_dimensions()[1] 21 height = property(_get_height) 22 23 def _get_image_dimensions(self): 24 if not hasattr(self, '_dimensions_cache'): 25 self._dimensions_cache = get_image_dimensions(self) 26 return self._dimensions_cache 27 28 def get_image_dimensions(file_or_path): 29 """Returns the (width, height) of an image, given an open file or a path.""" 30 p = PIL.Parser() 31 if hasattr(file_or_path, 'read'): 32 file = file_or_path 33 else: 34 file = open(file_or_path, 'rb') 35 while 1: 36 data = file.read(1024) 37 if not data: 38 break 39 p.feed(data) 40 if p.image: 41 return p.image.size 42 return None -
django/core/files/remote.py
1 from StringIO import StringIO 2 3 class RemoteFile(StringIO): 4 """Sends files to remote storage automatically, when necessary.""" 5 6 def __init__(self, data, mode, writer): 7 self._mode = mode 8 self._write_to_storage = writer 9 self._is_dirty = False 10 StringIO.__init__(self, data) 11 12 def write(self, data): 13 if 'w' not in self._mode: 14 raise AttributeError("File was opened for read-only access.") 15 StringIO.write(self, data) 16 self._is_dirty = True 17 18 def close(self): 19 if self._is_dirty: 20 self._write_to_storage(self.getvalue()) 21 StringIO.close(self) -
django/core/files/storage.py
1 import os 2 import urlparse 3 4 from django.conf import settings 5 from django.core.exceptions import ImproperlyConfigured, SuspiciousOperation 6 from django.utils.encoding import force_unicode, smart_str 7 from django.utils.text import force_unicode, get_valid_filename 8 from django.utils._os import safe_join 9 from django.core.files import locks, File 10 11 class Storage(object): 12 """ 13 A base storage class, providing some default behaviors that all other 14 storage systems can inherit or override, as necessary. 15 """ 16 def get_valid_filename(self, filename): 17 return get_valid_filename(filename) 18 19 def get_available_filename(self, filename): 20 # If the filename already exists, keep adding an underscore to the name 21 # of the file until the filename doesn't exist. 22 while self.exists(filename): 23 try: 24 dot_index = filename.rindex('.') 25 except ValueError: # filename has no dot 26 filename += '_' 27 else: 28 filename = filename[:dot_index] + '_' + filename[dot_index:] 29 return filename 30 31 class FileSystemStorage(Storage): 32 """ 33 Standard filesystem storage 34 """ 35 36 def __init__(self, location=settings.MEDIA_ROOT, base_url=settings.MEDIA_URL): 37 self.location = os.path.abspath(location) 38 self.base_url = base_url 39 40 def path(self, name): 41 try: 42 path = safe_join(self.location, name) 43 except ValueError: 44 raise SuspiciousOperation("Attempted access to '%s' denied." % name) 45 return os.path.normpath(path) 46 47 def size(self, name): 48 return os.path.getsize(self.path(name)) 49 50 def url(self, name): 51 if self.base_url is None: 52 raise ValueError("This file is not accessible via a URL.") 53 return urlparse.urljoin(self.base_url, name).replace('\\', '/') 54 55 def exists(self, name): 56 return os.path.exists(self.path(name)) 57 58 def open(self, name, mode='rb', mixin=None): 59 file = self._open(name, mode) 60 if mixin: 61 file.__class__ = type(mixin.__name__, (mixin, file.__class__), {}) 62 return file 63 64 def _open(self, name, mode='rb'): 65 return File(open(self.path(name), mode)) 66 67 def save(self, name, content): 68 # Check for old-style usage. Warn here first since there are multiple 69 # locations where we need to support both new and old usage. 70 if isinstance(content, basestring): 71 import warnings 72 warnings.warn( 73 message = "Representing uploaded files as strings is deprecated. Use django.core.files.uploadedfile.SimpleUploadedFile instead.", 74 category = DeprecationWarning, 75 stacklevel = 2 76 ) 77 from django.core.files.uploadedfile import SimpleUploadedFile 78 content = SimpleUploadedFile(name, content) 79 80 if name is None: 81 name = content.name 82 name = self.get_available_filename(name) 83 full_path = self.path(name) 84 85 directory = os.path.dirname(full_path) 86 if not os.path.exists(directory): 87 os.makedirs(directory) 88 elif not os.path.isdir(directory): 89 raise IOError("%s exists and is not a directory." % directory) 90 91 if hasattr(content, 'temporary_file_path'): 92 # This file has a file path that we can move. 93 content.close() 94 file_move_safe(content.temporary_file_path(), full_path) 95 else: 96 # This is a normal uploadedfile that we can stream. 97 fp = open(full_path, 'wb') 98 locks.lock(fp, locks.LOCK_EX) 99 for chunk in content.chunks(): 100 fp.write(chunk) 101 locks.unlock(fp) 102 fp.close() 103 104 # Store filenames with forward slashes, even on Windows 105 return force_unicode(name.replace('\\', '/')) 106 107 def delete(self, name): 108 filename = self.path(name) 109 # If the file exists, delete it from the filesystem. 110 if os.path.exists(filename): 111 os.remove(filename) 112 113 def get_storage(import_path): 114 try: 115 dot = import_path.rindex('.') 116 except ValueError: 117 raise ImproperlyConfigured("%s isn't a storage module." % import_path) 118 module, classname = import_path[:dot], import_path[dot+1:] 119 try: 120 mod = __import__(module, {}, {}, ['']) 121 except ImportError, e: 122 raise ImproperlyConfigured('Error importing storage module %s: "%s"' % (module, e)) 123 try: 124 storage_class = getattr(mod, classname) 125 except AttributeError: 126 raise ImproperlyConfigured('Storage module "%s" does not define a "%s" class.' % (module, classname)) 127 return storage_class() 128 129 default_storage = get_storage(settings.DEFAULT_FILE_STORAGE) -
django/core/files/uploadedfile.py
3 3 """ 4 4 5 5 import os 6 import tempfile7 6 import warnings 8 7 try: 9 8 from cStringIO import StringIO … … 11 10 from StringIO import StringIO 12 11 13 12 from django.conf import settings 13 from django.core.files.base import File 14 14 15 import tempfile 16 15 17 __all__ = ('UploadedFile', 'TemporaryUploadedFile', 'InMemoryUploadedFile', 'SimpleUploadedFile') 16 18 17 19 # Because we fooled around with it a bunch, UploadedFile has a bunch … … 38 40 else: 39 41 return property(getter, setter) 40 42 41 class UploadedFile( object):43 class UploadedFile(File): 42 44 """ 43 45 A abstract uploaded file (``TemporaryUploadedFile`` and 44 46 ``InMemoryUploadedFile`` are the built-in concrete subclasses). … … 75 77 76 78 name = property(_get_name, _set_name) 77 79 78 def chunks(self, chunk_size=None):79 """80 Read the file and yield chucks of ``chunk_size`` bytes (defaults to81 ``UploadedFile.DEFAULT_CHUNK_SIZE``).82 """83 if not chunk_size:84 chunk_size = UploadedFile.DEFAULT_CHUNK_SIZE85 86 if hasattr(self, 'seek'):87 self.seek(0)88 # Assume the pointer is at zero...89 counter = self.size90 91 while counter > 0:92 yield self.read(chunk_size)93 counter -= chunk_size94 95 80 # Deprecated properties 96 81 filename = deprecated_property(old="filename", new="name") 97 82 file_name = deprecated_property(old="file_name", new="name") … … 107 92 return self.read() 108 93 data = property(_get_data) 109 94 110 def multiple_chunks(self, chunk_size=None):111 """112 Returns ``True`` if you can expect multiple chunks.113 114 NB: If a particular file representation is in memory, subclasses should115 always return ``False`` -- there's no good reason to read from memory in116 chunks.117 """118 if not chunk_size:119 chunk_size = UploadedFile.DEFAULT_CHUNK_SIZE120 return self.size > chunk_size121 122 95 # Abstract methods; subclasses *must* define read() and probably should 123 96 # define open/close. 124 97 def read(self, num_bytes=None): … … 130 103 def close(self): 131 104 pass 132 105 133 def xreadlines(self):134 return self135 136 def readlines(self):137 return list(self.xreadlines())138 139 def __iter__(self):140 # Iterate over this file-like object by newlines141 buffer_ = None142 for chunk in self.chunks():143 chunk_buffer = StringIO(chunk)144 145 for line in chunk_buffer:146 if buffer_:147 line = buffer_ + line148 buffer_ = None149 150 # If this is the end of a line, yield151 # otherwise, wait for the next round152 if line[-1] in ('\n', '\r'):153 yield line154 else:155 buffer_ = line156 157 if buffer_ is not None:158 yield buffer_159 160 106 # Backwards-compatible support for uploaded-files-as-dictionaries. 161 107 def __getitem__(self, key): 162 108 warnings.warn( -
django/db/models/__init__.py
8 8 from django.db.models.base import Model 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
3 3 import sys 4 4 import os 5 5 from itertools import izip 6 from warnings import warn 6 7 try: 7 8 set 8 9 except NameError: … … 12 13 import django.db.models.manager # Ditto. 13 14 from django.core import validators 14 15 from django.core.exceptions import ObjectDoesNotExist, MultipleObjectsReturned, FieldError 15 from django.db.models.fields import AutoField, ImageField,FieldDoesNotExist16 from django.db.models.fields import AutoField, FieldDoesNotExist 16 17 from django.db.models.fields.related import OneToOneRel, ManyToOneRel, OneToOneField 17 18 from django.db.models.query import delete_objects, Q, CollectedObjects 18 19 from django.db.models.options import Options … … 458 459 return getattr(self, cachename) 459 460 460 461 def _get_FIELD_filename(self, field): 461 if getattr(self, field.attname): # Value is not blank. 462 return os.path.normpath(os.path.join(settings.MEDIA_ROOT, getattr(self, field.attname))) 463 return '' 462 warn("instance.get_%s_filename() is deprecated. Use instance.%s.path instead." % \ 463 (field.attname, field.attname), DeprecationWarning, stacklevel=3) 464 try: 465 return getattr(self, field.attname).path 466 except ValueError: 467 return '' 464 468 465 469 def _get_FIELD_url(self, field): 466 if getattr(self, field.attname): # Value is not blank. 467 import urlparse 468 return urlparse.urljoin(settings.MEDIA_URL, getattr(self, field.attname)).replace('\\', '/') 469 return '' 470 warn("instance.get_%s_url() is deprecated. Use instance.%s.url instead." % \ 471 (field.attname, field.attname), DeprecationWarning, stacklevel=3) 472 try: 473 return getattr(self, field.attname).url 474 except ValueError: 475 return '' 470 476 471 477 def _get_FIELD_size(self, field): 472 return os.path.getsize(self._get_FIELD_filename(field)) 478 warn("instance.get_%s_size() is deprecated. Use instance.%s.size instead." % \ 479 (field.attname, field.attname), DeprecationWarning, stacklevel=3) 480 return getattr(self, field.attname).size 473 481 474 def _save_FIELD_file(self, field, filename, raw_field, save=True): 475 # Create the upload directory if it doesn't already exist 476 directory = os.path.join(settings.MEDIA_ROOT, field.get_directory_name()) 477 if not os.path.exists(directory): 478 os.makedirs(directory) 479 elif not os.path.isdir(directory): 480 raise IOError('%s exists and is not a directory' % directory) 482 def _save_FIELD_file(self, field, filename, content, save=True): 483 warn("instance.save_%s_file() is deprecated. Use instance.%s.save() instead." % \ 484 (field.attname, field.attname), DeprecationWarning, stacklevel=3) 485 return getattr(self, field.attname).save(filename, content, save) 481 486 482 # Check for old-style usage (files-as-dictionaries). Warn here first483 # since there are multiple locations where we need to support both new484 # and old usage.485 if isinstance(raw_field, dict):486 import warnings487 warnings.warn(488 message = "Representing uploaded files as dictionaries is deprecated. Use django.core.files.uploadedfile.SimpleUploadedFile instead.",489 category = DeprecationWarning,490 stacklevel = 2491 )492 from django.core.files.uploadedfile import SimpleUploadedFile493 raw_field = SimpleUploadedFile.from_dict(raw_field)494 495 elif isinstance(raw_field, basestring):496 import warnings497 warnings.warn(498 message = "Representing uploaded files as strings is deprecated. Use django.core.files.uploadedfile.SimpleUploadedFile instead.",499 category = DeprecationWarning,500 stacklevel = 2501 )502 from django.core.files.uploadedfile import SimpleUploadedFile503 raw_field = SimpleUploadedFile(filename, raw_field)504 505 if filename is None:506 filename = raw_field.file_name507 508 filename = field.get_filename(filename)509 510 # If the filename already exists, keep adding an underscore to the name511 # of the file until the filename doesn't exist.512 while os.path.exists(os.path.join(settings.MEDIA_ROOT, filename)):513 try:514 dot_index = filename.rindex('.')515 except ValueError: # filename has no dot.516 filename += '_'517 else:518 filename = filename[:dot_index] + '_' + filename[dot_index:]519 520 # Save the file name on the object and write the file to disk.521 setattr(self, field.attname, filename)522 full_filename = self._get_FIELD_filename(field)523 if hasattr(raw_field, 'temporary_file_path'):524 # This file has a file path that we can move.525 raw_field.close()526 file_move_safe(raw_field.temporary_file_path(), full_filename)527 else:528 # This is a normal uploadedfile that we can stream.529 fp = open(full_filename, 'wb')530 locks.lock(fp, locks.LOCK_EX)531 for chunk in raw_field.chunks():532 fp.write(chunk)533 locks.unlock(fp)534 fp.close()535 536 # Save the width and/or height, if applicable.537 if isinstance(field, ImageField) and \538 (field.width_field or field.height_field):539 from django.utils.images import get_image_dimensions540 width, height = get_image_dimensions(full_filename)541 if field.width_field:542 setattr(self, field.width_field, width)543 if field.height_field:544 setattr(self, field.height_field, height)545 546 # Save the object because it has changed, unless save is False.547 if save:548 self.save()549 550 487 _save_FIELD_file.alters_data = True 551 488 552 489 def _get_FIELD_width(self, field): 553 return self._get_image_dimensions(field)[0] 490 warn("instance.get_%s_width() is deprecated. Use instance.%s.width instead." % \ 491 (field.attname, field.attname), DeprecationWarning, stacklevel=3) 492 return getattr(self, field.attname).width() 554 493 555 494 def _get_FIELD_height(self, field): 556 return self._get_image_dimensions(field)[1] 495 warn("instance.get_%s_height() is deprecated. Use instance.%s.height instead." % \ 496 (field.attname, field.attname), DeprecationWarning, stacklevel=3) 497 return getattr(self, field.attname).height() 557 498 558 def _get_image_dimensions(self, field):559 cachename = "__%s_dimensions_cache" % field.name560 if not hasattr(self, cachename):561 from django.utils.images import get_image_dimensions562 filename = self._get_FIELD_filename(field)563 setattr(self, cachename, get_image_dimensions(filename))564 return getattr(self, cachename)565 499 566 567 500 ############################################ 568 501 # HELPER FUNCTIONS (CURRIED MODEL METHODS) # 569 502 ############################################ -
django/db/models/fields/__init__.py
8 8 from django.utils import _decimal as decimal # for Python 2.3 9 9 10 10 from django.db import connection, get_creation_module 11 from django.db.models import signals12 11 from django.db.models.query_utils import QueryWrapper 13 12 from django.dispatch import dispatcher 14 13 from django.conf import settings … … 759 758 defaults.update(kwargs) 760 759 return super(EmailField, self).formfield(**defaults) 761 760 762 class FileField(Field):763 def __init__(self, verbose_name=None, name=None, upload_to='', **kwargs):764 self.upload_to = upload_to765 kwargs['max_length'] = kwargs.get('max_length', 100)766 Field.__init__(self, verbose_name, name, **kwargs)767 768 def get_internal_type(self):769 return "FileField"770 771 def get_db_prep_save(self, value):772 "Returns field's value prepared for saving into a database."773 # Need to convert UploadedFile objects provided via a form to unicode for database insertion774 if hasattr(value, 'name'):775 return value.name776 elif value is None:777 return None778 else:779 return unicode(value)780 781 def get_manipulator_fields(self, opts, manipulator, change, name_prefix='', rel=False, follow=True):782 field_list = Field.get_manipulator_fields(self, opts, manipulator, change, name_prefix, rel, follow)783 if not self.blank:784 if rel:785 # This validator makes sure FileFields work in a related context.786 class RequiredFileField(object):787 def __init__(self, other_field_names, other_file_field_name):788 self.other_field_names = other_field_names789 self.other_file_field_name = other_file_field_name790 self.always_test = True791 def __call__(self, field_data, all_data):792 if not all_data.get(self.other_file_field_name, False):793 c = validators.RequiredIfOtherFieldsGiven(self.other_field_names, ugettext_lazy("This field is required."))794 c(field_data, all_data)795 # First, get the core fields, if any.796 core_field_names = []797 for f in opts.fields:798 if f.core and f != self:799 core_field_names.extend(f.get_manipulator_field_names(name_prefix))800 # Now, if there are any, add the validator to this FormField.801 if core_field_names:802 field_list[0].validator_list.append(RequiredFileField(core_field_names, field_list[1].field_name))803 else:804 v = validators.RequiredIfOtherFieldNotGiven(field_list[1].field_name, ugettext_lazy("This field is required."))805 v.always_test = True806 field_list[0].validator_list.append(v)807 field_list[0].is_required = field_list[1].is_required = False808 809 # If the raw path is passed in, validate it's under the MEDIA_ROOT.810 def isWithinMediaRoot(field_data, all_data):811 f = os.path.abspath(os.path.join(settings.MEDIA_ROOT, field_data))812 if not f.startswith(os.path.abspath(os.path.normpath(settings.MEDIA_ROOT))):813 raise validators.ValidationError, _("Enter a valid filename.")814 field_list[1].validator_list.append(isWithinMediaRoot)815 return field_list816 817 def contribute_to_class(self, cls, name):818 super(FileField, self).contribute_to_class(cls, name)819 setattr(cls, 'get_%s_filename' % self.name, curry(cls._get_FIELD_filename, field=self))820 setattr(cls, 'get_%s_url' % self.name, curry(cls._get_FIELD_url, field=self))821 setattr(cls, 'get_%s_size' % self.name, curry(cls._get_FIELD_size, field=self))822 setattr(cls, 'save_%s_file' % self.name, lambda instance, filename, raw_field, save=True: instance._save_FIELD_file(self, filename, raw_field, save))823 dispatcher.connect(self.delete_file, signal=signals.post_delete, sender=cls)824 825 def delete_file(self, instance):826 if getattr(instance, self.attname):827 file_name = getattr(instance, 'get_%s_filename' % self.name)()828 # If the file exists and no other object of this type references it,829 # delete it from the filesystem.830 if os.path.exists(file_name) and \831 not instance.__class__._default_manager.filter(**{'%s__exact' % self.name: getattr(instance, self.attname)}):832 os.remove(file_name)833 834 def get_manipulator_field_objs(self):835 return [oldforms.FileUploadField, oldforms.HiddenField]836 837 def get_manipulator_field_names(self, name_prefix):838 return [name_prefix + self.name + '_file', name_prefix + self.name]839 840 def save_file(self, new_data, new_object, original_object, change, rel, save=True):841 upload_field_name = self.get_manipulator_field_names('')[0]842 if new_data.get(upload_field_name, False):843 if rel:844 file = new_data[upload_field_name][0]845 else:846 file = new_data[upload_field_name]847 848 if not file:849 return850 851 # Backwards-compatible support for files-as-dictionaries.852 # We don't need to raise a warning because Model._save_FIELD_file will853 # do so for us.854 try:855 file_name = file.name856 except AttributeError:857 file_name = file['filename']858 859 func = getattr(new_object, 'save_%s_file' % self.name)860 func(file_name, file, save)861 862 def get_directory_name(self):863 return os.path.normpath(force_unicode(datetime.datetime.now().strftime(smart_str(self.upload_to))))864 865 def get_filename(self, filename):866 from django.utils.text import get_valid_filename867 f = os.path.join(self.get_directory_name(), get_valid_filename(os.path.basename(filename)))868 return os.path.normpath(f)869 870 def save_form_data(self, instance, data):871 from django.core.files.uploadedfile import UploadedFile872 if data and isinstance(data, UploadedFile):873 getattr(instance, "save_%s_file" % self.name)(data.name, data, save=False)874 875 def formfield(self, **kwargs):876 defaults = {'form_class': forms.FileField}877 # If a file has been provided previously, then the form doesn't require878 # that a new file is provided this time.879 # The code to mark the form field as not required is used by880 # form_for_instance, but can probably be removed once form_for_instance881 # is gone. ModelForm uses a different method to check for an existing file.882 if 'initial' in kwargs:883 defaults['required'] = False884 defaults.update(kwargs)885 return super(FileField, self).formfield(**defaults)886 887 761 class FilePathField(Field): 888 762 def __init__(self, verbose_name=None, name=None, path='', match=None, recursive=False, **kwargs): 889 763 self.path, self.match, self.recursive = path, match, recursive … … 920 794 defaults.update(kwargs) 921 795 return super(FloatField, self).formfield(**defaults) 922 796 923 class ImageField(FileField):924 def __init__(self, verbose_name=None, name=None, width_field=None, height_field=None, **kwargs):925 self.width_field, self.height_field = width_field, height_field926 FileField.__init__(self, verbose_name, name, **kwargs)927 928 def get_manipulator_field_objs(self):929 return [oldforms.ImageUploadField, oldforms.HiddenField]930 931 def contribute_to_class(self, cls, name):932 super(ImageField, self).contribute_to_class(cls, name)933 # Add get_BLAH_width and get_BLAH_height methods, but only if the934 # image field doesn't have width and height cache fields.935 if not self.width_field:936 setattr(cls, 'get_%s_width' % self.name, curry(cls._get_FIELD_width, field=self))937 if not self.height_field:938 setattr(cls, 'get_%s_height' % self.name, curry(cls._get_FIELD_height, field=self))939 940 def save_file(self, new_data, new_object, original_object, change, rel, save=True):941 FileField.save_file(self, new_data, new_object, original_object, change, rel, save)942 # If the image has height and/or width field(s) and they haven't943 # changed, set the width and/or height field(s) back to their original944 # values.945 if change and (self.width_field or self.height_field) and save:946 if self.width_field:947 setattr(new_object, self.width_field, getattr(original_object, self.width_field))948 if self.height_field:949 setattr(new_object, self.height_field, getattr(original_object, self.height_field))950 new_object.save()951 952 def formfield(self, **kwargs):953 defaults = {'form_class': forms.ImageField}954 defaults.update(kwargs)955 return super(ImageField, self).formfield(**defaults)956 957 797 class IntegerField(Field): 958 798 empty_strings_allowed = False 959 799 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.files.base import File, ContentFile 7 from django.core.files.storage import default_storage 8 from django.core.files.images import ImageFile 9 from django.utils.functional import curry 10 from django.dispatch import dispatcher 11 from django.db.models import signals 12 from django.utils.encoding import force_unicode, smart_str 13 from django.utils.translation import ugettext_lazy, ugettext as _ 14 from django import oldforms 15 from django import forms 16 from django.core import validators 17 from django.db.models.loading import cache 18 19 class FieldFile(File): 20 def __init__(self, instance, field, name): 21 self.instance = instance 22 self.field = field 23 self.storage = field.storage 24 self.name = name or u'' 25 26 def __eq__(self, other): 27 # Older code may be expecting FileField values to be simple strings. 28 # By overriding the == operator, it can remain backwards compatibility. 29 if hasattr(other, 'name'): 30 return self.name == other.name 31 return self.name == other 32 33 # The standard File contains most of the necessary properties, but 34 # FieldFiles can be instantiated without a name, so that needs to 35 # be checked for here. 36 37 def _require_file(self): 38 if not self: 39 raise ValueError("The '%s' attribute has no file associated with it." % self.field.name) 40 41 def _get_file(self): 42 self._require_file() 43 if not hasattr(self, '_file'): 44 self._file = self.storage.open(self.name, 'rb') 45 return self._file 46 file = property(_get_file) 47 48 def _get_path(self): 49 self._require_file() 50 return self.storage.path(self.name) 51 path = property(_get_path) 52 53 def _get_url(self): 54 self._require_file() 55 return self.storage.url(self.name) 56 url = property(_get_url) 57 58 def open(self, mode='rb'): 59 self._require_file() 60 return super(FieldFile, self).open(mode) 61 62 # In addition to the standard File API, FieldFiles have extra methods 63 # to further manipulate the underlying file, as well as update the 64 # associated model instance. 65 66 def save(self, name, content, save=True): 67 name = self.field.generate_filename(self.instance, name) 68 self.name = self.storage.save(name, content) 69 setattr(self.instance, self.field.name, self.name) 70 71 # Update the filesize cache 72 self._size = len(content) 73 74 # Save the object because it has changed, unless save is False 75 if save: 76 self.instance.save() 77 78 def delete(self, save=True): 79 self._require_file() 80 self.storage.delete(self.name) 81 82 self.name = None 83 setattr(self.instance, self.field.name, self.name) 84 85 # Delete the filesize cache 86 if hasattr(self, '_size'): 87 del self._size 88 89 if save: 90 self.instance.save() 91 92 class FileDescriptor(object): 93 def __init__(self, field): 94 self.field = field 95 96 def __get__(self, instance=None, owner=None): 97 if instance is None: 98 raise AttributeError, "%s can only be accessed from %s instances." % (self.field.name(self.owner.__name__)) 99 return self.field.attr_class(instance, self.field, instance.__dict__[self.field.name]) 100 101 def __set__(self, instance, value): 102 instance.__dict__[self.field.name] = value 103 104 class FileField(Field): 105 attr_class = FieldFile 106 107 def __init__(self, verbose_name=None, name=None, upload_to='', storage=None, **kwargs): 108 for arg in ('core', 'primary_key', 'unique'): 109 if arg in kwargs: 110 raise TypeError("__init__() got an unexpected keyword argument '%s'" % arg) 111 112 self.storage = storage or default_storage 113 self.upload_to = upload_to 114 if callable(upload_to): 115 self.generate_filename = upload_to 116 117 kwargs['max_length'] = kwargs.get('max_length', 100) 118 super(FileField, self).__init__(verbose_name, name, **kwargs) 119 120 def get_internal_type(self): 121 return "FileField" 122 123 def get_db_prep_lookup(self, lookup_type, value): 124 if hasattr(value, 'name'): 125 value = value.name 126 return super(FileField, self).get_db_prep_lookup(lookup_type, value) 127 128 def get_db_prep_save(self, value): 129 "Returns field's value prepared for saving into a database." 130 # Need to convert UploadedFile objects provided via a form to unicode for database insertion 131 if value is None: 132 return None 133 return unicode(value.name) 134 135 def get_manipulator_fields(self, opts, manipulator, change, name_prefix='', rel=False, follow=True): 136 field_list = Field.get_manipulator_fields(self, opts, manipulator, change, name_prefix, rel, follow) 137 if not self.blank: 138 if rel: 139 # This validator makes sure FileFields work in a related context. 140 class RequiredFileField(object): 141 def __init__(self, other_field_names, other_file_field_name): 142 self.other_field_names = other_field_names 143 self.other_file_field_name = other_file_field_name 144 self.always_test = True 145 def __call__(self, field_data, all_data): 146 if not all_data.get(self.other_file_field_name, False): 147 c = validators.RequiredIfOtherFieldsGiven(self.other_field_names, ugettext_lazy("This field is required.")) 148 c(field_data, all_data) 149 # First, get the core fields, if any. 150 core_field_names = [] 151 for f in opts.fields: 152 if f.core and f != self: 153 core_field_names.extend(f.get_manipulator_field_names(name_prefix)) 154 # Now, if there are any, add the validator to this FormField. 155 if core_field_names: 156 field_list[0].validator_list.append(RequiredFileField(core_field_names, field_list[1].field_name)) 157 else: 158 v = validators.RequiredIfOtherFieldNotGiven(field_list[1].field_name, ugettext_lazy("This field is required.")) 159 v.always_test = True 160 field_list[0].validator_list.append(v) 161 field_list[0].is_required = field_list[1].is_required = False 162 163 # If the raw path is passed in, validate it's under the MEDIA_ROOT. 164 def isWithinMediaRoot(field_data, all_data): 165 f = os.path.abspath(os.path.join(settings.MEDIA_ROOT, field_data)) 166 if not f.startswith(os.path.abspath(os.path.normpath(settings.MEDIA_ROOT))): 167 raise validators.ValidationError(_("Enter a valid filename.")) 168 field_list[1].validator_list.append(isWithinMediaRoot) 169 return field_list 170 171 def contribute_to_class(self, cls, name): 172 super(FileField, self).contribute_to_class(cls, name) 173 setattr(cls, self.name, FileDescriptor(self)) 174 setattr(cls, 'get_%s_filename' % self.name, curry(cls._get_FIELD_filename, field=self)) 175 setattr(cls, 'get_%s_url' % self.name, curry(cls._get_FIELD_url, field=self)) 176 setattr(cls, 'get_%s_size' % self.name, curry(cls._get_FIELD_size, field=self)) 177 setattr(cls, 'save_%s_file' % self.name, lambda instance, name, content, save=True: instance._save_FIELD_file(self, name, content, save)) 178 dispatcher.connect(self.delete_file, signal=signals.post_delete, sender=cls) 179 180 def delete_file(self, instance, sender): 181 filename = getattr(instance, self.attname).name 182 # If no other object of this type references the file, 183 # and it's not the default value for future objects, 184 # delete it from the backend. 185 if filename and filename != self.default and \ 186 not sender._default_manager.filter(**{self.name: filename}): 187 self.storage.delete(filename) 188 189 def get_manipulator_field_objs(self): 190 return [oldforms.FileUploadField, oldforms.HiddenField] 191 192 def get_manipulator_field_names(self, name_prefix): 193 return [name_prefix + self.name + '_file', name_prefix + self.name] 194 195 def save_file(self, new_data, new_object, original_object, change, rel, save=True): 196 upload_field_name = self.get_manipulator_field_names('')[0] 197 if new_data.get(upload_field_name, False): 198 if rel: 199 file = new_data[upload_field_name][0] 200 else: 201 file = new_data[upload_field_name] 202 203 # Backwards-compatible support for files-as-dictionaries. 204 # We don't need to raise a warning because the storage backend will 205 # do so for us. 206 try: 207 filename = file.name 208 except AttributeError: 209 filename = file['filename'] 210 filename = self.get_filename(filename) 211 212 getattr(new_object, self.attname).save(filename, file, save) 213 214 def get_directory_name(self): 215 return os.path.normpath(force_unicode(datetime.datetime.now().strftime(smart_str(self.upload_to)))) 216 217 def get_filename(self, filename): 218 return os.path.normpath(self.storage.get_valid_filename(os.path.basename(filename))) 219 220 def generate_filename(self, instance, filename): 221 return os.path.join(self.get_directory_name(), self.get_filename(filename)) 222 223 def save_form_data(self, instance, data): 224 from django.core.files.uploadedfile import UploadedFile 225 if data and isinstance(data, UploadedFile): 226 getattr(instance, self.name).save(data.name, data, save=False) 227 228 def formfield(self, **kwargs): 229 defaults = {'form_class': forms.FileField} 230 # If a file has been provided previously, then the form doesn't require 231 # that a new file is provided this time. 232 # The code to mark the form field as not required is used by 233 # form_for_instance, but can probably be removed once form_for_instance 234 # is gone. ModelForm uses a different method to check for an existing file. 235 if 'initial' in kwargs: 236 defaults['required'] = False 237 defaults.update(kwargs) 238 return super(FileField, self).formfield(**defaults) 239 240 class ImageFieldFile(ImageFile, FieldFile): 241 def save(self, name, content, save=True): 242 super(ImageFieldFile, self).save(name, content, save) 243 244 # Update the cache for image dimensions 245 from django.core.files.images import get_image_dimensions 246 if not hasattr(content, 'read'): 247 content = ContentFile(name, content) 248 self._dimensions_cache = get_image_dimensions(content) 249 250 def delete(self, save=True): 251 # Clear the image dimensions cache 252 if hasattr(self, '_dimensions_cache'): 253 del self._dimensions_cache 254 255 super(ImageFieldFile, self).delete(save) 256 257 class ImageField(FileField): 258 attr_class = ImageFieldFile 259 260 def __init__(self, verbose_name=None, name=None, width_field=None, height_field=None, **kwargs): 261 self.width_field, self.height_field = width_field, height_field 262 FileField.__init__(self, verbose_name, name, **kwargs) 263 264 def get_manipulator_field_objs(self): 265 return [oldforms.ImageUploadField, oldforms.HiddenField] 266 267 def contribute_to_class(self, cls, name): 268 super(ImageField, self).contribute_to_class(cls, name) 269 # Add get_BLAH_width and get_BLAH_height methods, but only if the 270 # image field doesn't have width and height cache fields. 271 if not self.width_field: 272 setattr(cls, 'get_%s_width' % self.name, curry(cls._get_FIELD_width, field=self)) 273 if not self.height_field: 274 setattr(cls, 'get_%s_height' % self.name, curry(cls._get_FIELD_height, field=self)) 275 276 def save_file(self, new_data, new_object, original_object, change, rel, save=True): 277 # If the image has height and/or width field(s) and they haven't 278 # changed, set the width and/or height field(s) back to their original 279 # values. 280 if self.width_field or self.height_field: 281 if original_object and not change: 282 if self.width_field: 283 setattr(new_object, self.width_field, getattr(original_object, self.width_field)) 284 if self.height_field: 285 setattr(new_object, self.height_field, getattr(original_object, self.height_field)) 286 else: 287 from django.utils.images import get_image_dimensions 288 289 upload_field_name = self.get_manipulator_field_names('')[0] 290 if rel: 291 file = new_data[upload_field_name][0] 292 else: 293 file = new_data[upload_field_name] 294 295 # Get the width and height from the raw content to avoid extra 296 # unnecessary trips to the file backend. 297 width, height = get_image_dimensions(file) 298 299 if self.width_field: 300 setattr(new_object, self.width_field, width) 301 if self.height_field: 302 setattr(new_object, self.height_field, height) 303 super(ImageField, self).save_file(new_data, new_object, original_object, change, rel, save) 304 305 def formfield(self, **kwargs): 306 defaults = {'form_class': forms.ImageField} 307 defaults.update(kwargs) 308 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
1 """ 2 Utility functions for handling images. 1 import warnings 3 2 4 Requires PIL, as you might imagine. 5 """ 3 from django.core.files.images import get_image_dimensions 6 4 7 import ImageFile 8 9 def get_image_dimensions(path): 10 """Returns the (width, height) of an image at a given path.""" 11 p = ImageFile.Parser() 12 fp = open(path, 'rb') 13 while 1: 14 data = fp.read(1024) 15 if not data: 16 break 17 p.feed(data) 18 if p.image: 19 return p.image.size 20 break 21 fp.close() 22 return None 5 warnings.warn("django.utils.images has been moved to django.core.files.images.", DeprecationWarning) -
tests/modeltests/files/__init__.py
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.files.base import ContentFile 12 from django.core.files.storage import FileSystemStorage 13 from django.core.cache import cache 14 15 temp_storage = FileSystemStorage(location=tempfile.gettempdir()) 16 17 # Write out a file to be used as default content 18 temp_storage.save('tests/default.txt', ContentFile('default content')) 19 20 class Storage(models.Model): 21 def custom_upload_to(self, filename): 22 return 'foo' 23 24 normal = models.FileField(storage=temp_storage, upload_to='tests') 25 custom = models.FileField(storage=temp_storage, upload_to=custom_upload_to) 26 default = models.FileField(storage=temp_storage, upload_to='tests', default='tests/default.txt') 27 28 __test__ = {'API_TESTS':""" 29 # An object without a file has limited functionality 30 31 >>> obj1 = Storage() 32 >>> obj1.normal 33 <FieldFile: None> 34 >>> obj1.normal.size 35 Traceback (most recent call last): 36 ... 37 ValueError: The 'normal' attribute has no file associated with it. 38 39 # Saving a file enables full functionality 40 41 >>> obj1.normal.save('django_test.txt', ContentFile('content')) 42 >>> obj1.normal 43 <FieldFile: tests/django_test.txt> 44 >>> obj1.normal.size 45 7 46 >>> obj1.normal.read() 47 'content' 48 49 # Save another file with the same name 50 51 >>> obj2 = Storage() 52 >>> obj2.normal.save('django_test.txt', ContentFile('more content')) 53 >>> obj2.normal 54 <FieldFile: tests/django_test_.txt> 55 >>> obj2.normal.size 56 12 57 58 # Push the objects into the cache to make sure they pickle properly 59 60 >>> cache.set('obj1', obj1) 61 >>> cache.set('obj2', obj2) 62 >>> cache.get('obj2').normal 63 <FieldFile: tests/django_test_.txt> 64 65 # Deleting an object deletes the file it uses, if there are no other objects 66 # still using that file 67 68 >>> obj2.delete() 69 >>> obj2.normal.save('django_test.txt', ContentFile('more content')) 70 >>> obj2.normal 71 <FieldFile: tests/django_test_.txt> 72 73 # Default values allow an object to access a single file 74 75 >>> obj3 = Storage.objects.create() 76 >>> obj3.default 77 <FieldFile: tests/default.txt> 78 >>> obj3.default.read() 79 'default content' 80 81 # But it shouldn't be deleted, even if there are no more objects using it 82 83 >>> obj3.delete() 84 >>> obj3 = Storage() 85 >>> obj3.default.read() 86 'default content' 87 88 # Clean up the temporary files 89 90 >>> obj1.normal.delete() 91 >>> obj2.normal.delete() 92 >>> obj3.default.delete() 93 """} -
tests/modeltests/model_forms/models.py
11 11 import tempfile 12 12 13 13 from django.db import models 14 from django.core.files.storage 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 … … 71 74 # If PIL is available, try testing PIL. 72 75 # Otherwise, it's equivalent to TextFile above. 73 76 import Image 74 image = models.ImageField( upload_to=tempfile.gettempdir())77 image = models.ImageField(storage=temp_storage, upload_to='tests') 75 78 except ImportError: 76 image = models.FileField( upload_to=tempfile.gettempdir())79 image = models.FileField(storage=temp_storage, upload_to='tests') 77 80 78 81 def __unicode__(self): 79 82 return self.description … … 784 787 785 788 # FileField ################################################################### 786 789 790 # File forms. 791 787 792 >>> class TextFileForm(ModelForm): 788 793 ... class Meta: 789 794 ... model = TextFile … … 806 811 <class 'django.core.files.uploadedfile.SimpleUploadedFile'> 807 812 >>> instance = f.save() 808 813 >>> instance.file 809 u'...test1.txt' 814 <FieldFile: tests/test1.txt> 810 815 811 >>> os.unlink(instance.get_file_filename())816 >>> instance.file.delete() 812 817 813 818 >>> f = TextFileForm(data={'description': u'Assistance'}, files={'file': SimpleUploadedFile('test1.txt', 'hello world')}) 814 819 >>> f.is_valid() … … 817 822 <class 'django.core.files.uploadedfile.SimpleUploadedFile'> 818 823 >>> instance = f.save() 819 824 >>> instance.file 820 u'...test1.txt' 825 <FieldFile: tests/test1.txt> 821 826 822 827 # Edit an instance that already has the file defined in the model. This will not 823 828 # save the file again, but leave it exactly as it is. … … 826 831 >>> f.is_valid() 827 832 True 828 833 >>> f.cleaned_data['file'] 829 u'...test1.txt' 834 <FieldFile: tests/test1.txt> 830 835 >>> instance = f.save() 831 836 >>> instance.file 832 u'...test1.txt' 837 <FieldFile: tests/test1.txt> 833 838 834 839 # Delete the current file since this is not done by Django. 835 >>> os.unlink(instance.get_file_filename())840 >>> instance.file.delete() 836 841 837 842 # Override the file by uploading a new one. 838 843 … … 841 846 True 842 847 >>> instance = f.save() 843 848 >>> instance.file 844 u'...test2.txt' 849 <FieldFile: tests/test2.txt> 845 850 846 851 # Delete the current file since this is not done by Django. 847 >>> os.unlink(instance.get_file_filename())852 >>> instance.file.delete() 848 853 849 854 >>> f = TextFileForm(data={'description': u'Assistance'}, files={'file': SimpleUploadedFile('test2.txt', 'hello world')}) 850 855 >>> f.is_valid() 851 856 True 852 857 >>> instance = f.save() 853 858 >>> instance.file 854 u'...test2.txt' 859 <FieldFile: tests/test2.txt> 855 860 856 861 # Delete the current file since this is not done by Django. 857 >>> os.unlink(instance.get_file_filename())862 >>> instance.file.delete() 858 863 859 864 >>> instance.delete() 860 865 … … 866 871 True 867 872 >>> instance = f.save() 868 873 >>> instance.file 869 '' 874 <FieldFile: None> 870 875 871 876 >>> f = TextFileForm(data={'description': u'Assistance'}, files={'file': SimpleUploadedFile('test3.txt', 'hello world')}, instance=instance) 872 877 >>> f.is_valid() 873 878 True 874 879 >>> instance = f.save() 875 880 >>> instance.file 876 u'...test3.txt' 881 <FieldFile: tests/test3.txt> 877 882 878 883 # Delete the current file since this is not done by Django. 879 >>> os.unlink(instance.get_file_filename())884 >>> instance.file.delete() 880 885 >>> instance.delete() 881 886 882 887 >>> f = TextFileForm(data={'description': u'Assistance'}, files={'file': SimpleUploadedFile('test3.txt', 'hello world')}) … … 884 889 True 885 890 >>> instance = f.save() 886 891 >>> instance.file 887 u'...test3.txt' 892 <FieldFile: tests/test3.txt> 888 893 889 894 # Delete the current file since this is not done by Django. 890 >>> os.unlink(instance.get_file_filename())895 >>> instance.file.delete() 891 896 >>> instance.delete() 892 897 893 898 # ImageField ################################################################### … … 909 914 <class 'django.core.files.uploadedfile.SimpleUploadedFile'> 910 915 >>> instance = f.save() 911 916 >>> instance.image 912 u'...test.png' 917 <ImageFieldFile: tests/test.png> 913 918 914 919 # Delete the current file since this is not done by Django. 915 >>> os.unlink(instance.get_image_filename())920 >>> instance.image.delete() 916 921 917 922 >>> f = ImageFileForm(data={'description': u'An image'}, files={'image': SimpleUploadedFile('test.png', image_data)}) 918 923 >>> f.is_valid() … … 921 926 <class 'django.core.files.uploadedfile.SimpleUploadedFile'> 922 927 >>> instance = f.save() 923 928 >>> instance.image 924 u'...test.png' 929 <ImageFieldFile: tests/test.png> 925 930 926 931 # Edit an instance that already has the image defined in the model. This will not 927 932 # save the image again, but leave it exactly as it is. … … 930 935 >>> f.is_valid() 931 936 True 932 937 >>> f.cleaned_data['image'] 933 u'...test.png' 938 <ImageFieldFile: tests/test.png> 934 939 >>> instance = f.save() 935 940 >>> instance.image 936 u'...test.png' 941 <ImageFieldFile: tests/test.png> 937 942 938 943 # Delete the current image since this is not done by Django. 939 944 940 >>> os.unlink(instance.get_image_filename())945 >>> instance.image.delete() 941 946 942 947 # Override the file by uploading a new one. 943 948 … … 946 951 True 947 952 >>> instance = f.save() 948 953 >>> instance.image 949 u'...test2.png' 954 <ImageFieldFile: tests/test2.png> 950 955 951 956 # Delete the current file since this is not done by Django. 952 >>> os.unlink(instance.get_image_filename())957 >>> instance.image.delete() 953 958 >>> instance.delete() 954 959 955 960 >>> f = ImageFileForm(data={'description': u'Changed it'}, files={'image': SimpleUploadedFile('test2.png', image_data)}) … … 957 962 True 958 963 >>> instance = f.save() 959 964 >>> instance.image 960 u'...test2.png' 965 <ImageFieldFile: tests/test2.png> 961 966 962 967 # Delete the current file since this is not done by Django. 963 >>> os.unlink(instance.get_image_filename())968 >>> instance.image.delete() 964 969 >>> instance.delete() 965 970 966 971 # Test the non-required ImageField … … 971 976 True 972 977 >>> instance = f.save() 973 978 >>> instance.image 974 '' 979 <ImageFieldFile: None> 975 980 976 981 >>> f = ImageFileForm(data={'description': u'And a final one'}, files={'image': SimpleUploadedFile('test3.png', image_data)}, instance=instance) 977 982 >>> f.is_valid() 978 983 True 979 984 >>> instance = f.save() 980 985 >>> instance.image 981 u'...test3.png' 986 <ImageFieldFile: tests/test3.png> 982 987 983 988 # Delete the current file since this is not done by Django. 984 >>> os.unlink(instance.get_image_filename())989 >>> instance.image.delete() 985 990 >>> instance.delete() 986 991 987 992 >>> f = ImageFileForm(data={'description': u'And a final one'}, files={'image': SimpleUploadedFile('test3.png', image_data)}) … … 989 994 True 990 995 >>> instance = f.save() 991 996 >>> instance.image 992 u'...test3.png' 997 <ImageFieldFile: tests/test3.png> 993 998 >>> instance.delete() 994 999 995 1000 # Media on a ModelForm ######################################################## -
tests/regressiontests/bug639/models.py
1 1 import tempfile 2 2 3 from django.db import models 4 from django.core.files.storage 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 +=1 17 No newline at end of file 20 self._savecount += 1 -
tests/regressiontests/bug639/tests.py
36 36 Make sure to delete the "uploaded" file to avoid clogging /tmp. 37 37 """ 38 38 p = Photo.objects.get() 39 os.unlink(p.get_image_filename())39 p.image.delete(save=False) -
tests/regressiontests/file_uploads/models.py
1 1 import tempfile 2 2 import os 3 3 from django.db import models 4 from django.core.files.storage import FileSystemStorage 4 5 5 UPLOAD_ROOT = tempfile.mkdtemp()6 UPLOAD_TO = os.path.join( UPLOAD_ROOT, 'test_upload')6 temp_storage = FileSystemStorage(tempfile.mkdtemp()) 7 UPLOAD_TO = os.path.join(temp_storage.location, 'test_upload') 7 8 8 9 class FileModel(models.Model): 9 testfile = models.FileField( upload_to=UPLOAD_TO)10 testfile = models.FileField(storage=temp_storage, upload_to='test_upload') -
tests/regressiontests/file_uploads/tests.py
9 9 from django.test import TestCase, client 10 10 from django.utils import simplejson 11 11 12 from models import FileModel, UPLOAD_ROOT, UPLOAD_TO12 from models import FileModel, temp_storage, UPLOAD_TO 13 13 14 14 class FileUploadTests(TestCase): 15 15 def test_simple_upload(self): … … 194 194 """ 195 195 def setUp(self): 196 196 self.obj = FileModel() 197 if not os.path.isdir( UPLOAD_ROOT):198 os.makedirs( UPLOAD_ROOT)197 if not os.path.isdir(temp_storage.location): 198 os.makedirs(temp_storage.location) 199 199 200 200 def tearDown(self): 201 os.chmod( UPLOAD_ROOT, 0700)202 shutil.rmtree( UPLOAD_ROOT)201 os.chmod(temp_storage.location, 0700) 202 shutil.rmtree(temp_storage.location) 203 203 204 204 def test_readonly_root(self): 205 205 """Permission errors are not swallowed""" 206 os.chmod( UPLOAD_ROOT, 0500)206 os.chmod(temp_storage.location, 0500) 207 207 try: 208 self.obj. save_testfile_file('foo.txt', SimpleUploadedFile('foo.txt', 'x'))208 self.obj.testfile.save('foo.txt', SimpleUploadedFile('foo.txt', 'x')) 209 209 except OSError, err: 210 210 self.assertEquals(err.errno, errno.EACCES) 211 except :212 self.fail("OSError [Errno %s] not raised " % errno.EACCES)211 except Exception, err: 212 self.fail("OSError [Errno %s] not raised." % errno.EACCES) 213 213 214 214 def test_not_a_directory(self): 215 215 """The correct IOError is raised when the upload directory name exists but isn't a directory""" … … 217 217 fd = open(UPLOAD_TO, 'w') 218 218 fd.close() 219 219 try: 220 self.obj. save_testfile_file('foo.txt', SimpleUploadedFile('foo.txt', 'x'))220 self.obj.testfile.save('foo.txt', SimpleUploadedFile('foo.txt', 'x')) 221 221 except IOError, err: 222 222 # The test needs to be done on a specific string as IOError 223 223 # is raised even without the patch (just not early enough) 224 224 self.assertEquals(err.args[0], 225 "%s exists and is not a directory " % UPLOAD_TO)225 "%s exists and is not a directory." % UPLOAD_TO) 226 226 except: 227 227 self.fail("IOError not raised") -
tests/regressiontests/forms/models.py
29 29 >>> from django.core.files.uploadedfile import SimpleUploadedFile 30 30 31 31 # FileModel with unicode filename and data ######################### 32 >>> f = FileForm(data={}, files={'file1': SimpleUploadedFile(' 我隻氣墊船裝滿晒鱔.txt', 'मेरी मँडराने वाली नाव सर्पमीनों से भरी ह')}, auto_id=False)32 >>> f = FileForm(data={}, files={'file1': SimpleUploadedFile('?????????.txt', '???? ??????? ???? ??? ????????? ?? ??? ?')}, auto_id=False) 33 33 >>> f.is_valid() 34 34 True 35 35 >>> f.cleaned_data 36 {'file1': <SimpleUploadedFile: 我隻氣墊船裝滿晒鱔.txt (text/plain)>}36 {'file1': <SimpleUploadedFile: ?????????.txt (text/plain)>} 37 37 >>> m = FileModel.objects.create(file=f.cleaned_data['file1']) 38 38 39 39 # Boundary conditions on a PostitiveIntegerField ######################### -
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
144 144 (data_obj, 41, EmailData, None), 145 145 (data_obj, 42, EmailData, ""), 146 146 (data_obj, 50, FileData, 'file:///foo/bar/whiz.txt'), 147 (data_obj, 51, FileData, None),147 # (data_obj, 51, FileData, None), 148 148 (data_obj, 52, FileData, ""), 149 149 (data_obj, 60, FilePathData, "/foo/bar/whiz.txt"), 150 150 (data_obj, 61, FilePathData, None), … … 242 242 # (pk_obj, 620, DatePKData, datetime.date(2006,6,16)), 243 243 # (pk_obj, 630, DateTimePKData, datetime.datetime(2006,6,16,10,42,37)), 244 244 (pk_obj, 640, EmailPKData, "hovercraft@example.com"), 245 (pk_obj, 650, FilePKData, 'file:///foo/bar/whiz.txt'),245 # (pk_obj, 650, FilePKData, 'file:///foo/bar/whiz.txt'), 246 246 (pk_obj, 660, FilePathPKData, "/foo/bar/whiz.txt"), 247 247 (pk_obj, 670, DecimalPKData, decimal.Decimal('12.345')), 248 248 (pk_obj, 671, DecimalPKData, decimal.Decimal('-12.345')), -
tests/regressiontests/storage/__init__.py
1 -
tests/regressiontests/storage/models.py
1 # Empty file to force tests to run -
tests/regressiontests/storage/tests.py
1 """ 2 Tests for the file storage mechanism 3 4 >>> import tempfile 5 >>> from django.core.files.storage import FileSystemStorage 6 >>> from django.core.files.base import ContentFile 7 8 # Instantiate a storage system manually, specifying a location. 9 10 >>> temp_storage = FileSystemStorage(location=tempfile.gettempdir()) 11 12 # Standard file access options are available, and work as expected. 13 14 >>> temp_storage.exists('storage_test') 15 False 16 >>> file = temp_storage.open('storage_test', 'w') 17 >>> file.write('storage contents') 18 >>> file.close() 19 20 >>> temp_storage.exists('storage_test') 21 True 22 >>> file = temp_storage.open('storage_test', 'r') 23 >>> file.read() 24 'storage contents' 25 >>> file.close() 26 27 >>> temp_storage.delete('storage_test') 28 >>> temp_storage.exists('storage_test') 29 False 30 31 # Files can only be accessed if they're below the specified location. 32 33 >>> temp_storage.exists('..') 34 Traceback (most recent call last): 35 ... 36 SuspiciousOperation: Attempted access to '..' denied. 37 >>> temp_storage.open('/etc/passwd') 38 Traceback (most recent call last): 39 ... 40 SuspiciousOperation: Attempted access to '/etc/passwd' denied. 41 42 # RemoteFile allows files to be committed by way of a user-defined function. 43 44 >>> from django.core.files.remote import RemoteFile 45 >>> def write_file(contents): 46 ... print 'Writing %s' % contents 47 48 # Opening for read access doesn't commit back to the server 49 50 >>> file = RemoteFile('', 'r', write_file) 51 >>> file.close() 52 53 # The same goes for opening for write access, but not actually writing 54 55 >>> file = RemoteFile('', 'w', write_file) 56 >>> file.close() 57 58 # But once it's written to, it gets committed on close 59 60 >>> file = RemoteFile('', 'w', write_file) 61 >>> file.write('remote contents') # Content isn't committed yet 62 >>> file.close() # Content gets committed to the storage system 63 Writing remote contents 64 65 # Custom storage systems can be created to customize behavior 66 67 >>> class CustomStorage(FileSystemStorage): 68 ... def get_available_filename(self, filename): 69 ... # Append numbers to duplicate files rather than underscores, like Trac 70 ... 71 ... parts = filename.split('.') 72 ... basename, ext = parts[0], parts[1:] 73 ... number = 2 74 ... 75 ... while self.exists(filename): 76 ... filename = '.'.join([basename, str(number)] + ext) 77 ... number += 1 78 ... 79 ... return filename 80 >>> custom_storage = CustomStorage(tempfile.gettempdir()) 81 82 >>> first = custom_storage.save('custom_storage', ContentFile('custom contents')) 83 >>> first 84 u'custom_storage' 85 >>> second = custom_storage.save('custom_storage', ContentFile('more contents')) 86 >>> second 87 u'custom_storage.2' 88 >>> custom_storage.delete(first) 89 >>> custom_storage.delete(second) 90 """