Ticket #5361: 5361-r8156.diff
File 5361-r8156.diff, 100.6 KB (added by , 16 years ago) |
---|
-
django/conf/global_settings.py
226 226 # Path to the "jing" executable -- needed to validate XMLFields 227 227 JING_PATH = "/usr/bin/jing" 228 228 229 # Default file storage mechanism that holds media. 230 DEFAULT_FILE_STORAGE = 'django.core.files.storage.FileSystemStorage' 231 229 232 # Absolute path to the directory that holds media. 230 233 # Example: "/home/media/media.lawrence.com/" 231 234 MEDIA_ROOT = '' -
django/core/files/__init__.py
1 import os 2 3 from django.core.files.base import File 4 from django.core.files.storage import Storage, open -
django/core/files/base.py
1 import os 2 3 from django.utils.encoding import smart_str, smart_unicode 4 5 try: 6 from cStringIO import StringIO 7 except ImportError: 8 from StringIO import StringIO 9 10 class File(object): 11 DEFAULT_CHUNK_SIZE = 64 * 2**10 12 13 def __init__(self, file): 14 self.file = file 15 self._name = file.name 16 self._mode = file.mode 17 self._closed = False 18 19 def __str__(self): 20 return smart_str(self.name or '') 21 22 def __unicode__(self): 23 return smart_unicode(self.name or u'') 24 25 def __repr__(self): 26 return "<%s: %s>" % (self.__class__.__name__, self or "None") 27 28 def __nonzero__(self): 29 return not not self.name 30 31 def __len__(self): 32 return self.size 33 34 def _get_name(self): 35 return self._name 36 name = property(_get_name) 37 38 def _get_mode(self): 39 return self._mode 40 mode = property(_get_mode) 41 42 def _get_closed(self): 43 return self._closed 44 closed = property(_get_closed) 45 46 def _get_size(self): 47 if not hasattr(self, '_size'): 48 if hasattr(self.file, 'size'): 49 self._size = self.file.size 50 elif os.path.exists(self.file.name): 51 self._size = os.path.getsize(self.file.name) 52 else: 53 raise AttributeError("Unable to determine the file's size.") 54 return self._size 55 56 def _set_size(self, size): 57 self._size = size 58 59 size = property(_get_size, _set_size) 60 61 def chunks(self, chunk_size=None): 62 """ 63 Read the file and yield chucks of ``chunk_size`` bytes (defaults to 64 ``UploadedFile.DEFAULT_CHUNK_SIZE``). 65 """ 66 if not chunk_size: 67 chunk_size = self.__class__.DEFAULT_CHUNK_SIZE 68 69 if hasattr(self, 'seek'): 70 self.seek(0) 71 # Assume the pointer is at zero... 72 counter = self.size 73 74 while counter > 0: 75 yield self.read(chunk_size) 76 counter -= chunk_size 77 78 def multiple_chunks(self, chunk_size=None): 79 """ 80 Returns ``True`` if you can expect multiple chunks. 81 82 NB: If a particular file representation is in memory, subclasses should 83 always return ``False`` -- there's no good reason to read from memory in 84 chunks. 85 """ 86 if not chunk_size: 87 chunk_size = self.DEFAULT_CHUNK_SIZE 88 return self.size > chunk_size 89 90 def xreadlines(self): 91 return iter(self) 92 93 def readlines(self): 94 return list(self.xreadlines()) 95 96 def __iter__(self): 97 # Iterate over this file-like object by newlines 98 buffer_ = None 99 for chunk in self.chunks(): 100 chunk_buffer = StringIO(chunk) 101 102 for line in chunk_buffer: 103 if buffer_: 104 line = buffer_ + line 105 buffer_ = None 106 107 # If this is the end of a line, yield 108 # otherwise, wait for the next round 109 if line[-1] in ('\n', '\r'): 110 yield line 111 else: 112 buffer_ = line 113 114 if buffer_ is not None: 115 yield buffer_ 116 117 def open(self, mode='rb'): 118 if not self.closed: 119 self.seek(0) 120 elif os.path.exists(self.file.name): 121 self.file = open(self.file.name, self.file.mode) 122 else: 123 raise ValueError("The file cannot be reopened.") 124 125 def seek(self, position): 126 self.file.seek(position) 127 128 def tell(self): 129 return self.file.tell() 130 131 def read(self, num_bytes=None): 132 if num_bytes is None: 133 return self.file.read() 134 return self.file.read(num_bytes) 135 136 def write(self, content): 137 if not self.mode.startswith('w'): 138 raise IOError("File was not opened with write access.") 139 self.file.write(content) 140 141 def flush(self): 142 if not self.mode.startswith('w'): 143 raise IOError("File was not opened with write access.") 144 self.file.flush() 145 146 def close(self): 147 self.file.close() 148 self._closed = True 149 150 class ContentFile(File): 151 """ 152 A File-like object that takes just raw content, rather than an actual file. 153 """ 154 def __init__(self, content): 155 self.file = StringIO(content or '') 156 self.size = len(content or '') 157 self.file.seek(0) 158 self._closed = False 159 160 def __str__(self): 161 return 'Raw content' 162 163 def __nonzero__(self): 164 return True 165 166 def open(self, mode=None): 167 if self._closed: 168 self._closed = False 169 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 from __builtin__ import open as python_open 4 5 from django.conf import settings 6 from django.core.exceptions import ImproperlyConfigured, SuspiciousOperation 7 from django.utils.encoding import force_unicode, smart_str 8 from django.utils.text import force_unicode, get_valid_filename 9 from django.utils._os import safe_join 10 from django.core.files import locks, File 11 12 __all__ = ('StorageBase', 'Storage', 'FileSystemStorage', 'open') 13 14 class StorageBase(object): 15 """ 16 A base storage class, providing some default behaviors that all other 17 storage systems can inherit or override, as necessary. 18 """ 19 20 # The following methods represent a public interface to private methods. 21 # These shouldn't be overridden by subclasses unless absolutely necessary. 22 23 def open(self, name, mode='rb', mixin=None): 24 """ 25 Retrieves the specified file from storage, using the optional mixin 26 class to customize what features are available on the File returned. 27 """ 28 file = self._open(name, mode) 29 if mixin: 30 # Add the mixin as a parent class of the File returned from storage. 31 file.__class__ = type(mixin.__name__, (mixin, file.__class__), {}) 32 return file 33 34 def save(self, name, content): 35 """ 36 Saves new content to the file specified by name. The content should be a 37 proper File object, ready to be read from the beginning. 38 """ 39 # Check for old-style usage. Warn here first since there are multiple 40 # locations where we need to support both new and old usage. 41 if isinstance(content, basestring): 42 import warnings 43 warnings.warn( 44 message = "Representing files as strings is deprecated." \ 45 "Use django.core.files.base.ContentFile instead.", 46 category = DeprecationWarning, 47 stacklevel = 2 48 ) 49 from django.core.files.base import ContentFile 50 content = ContentFile(content) 51 52 # Get the proper name for the file, as it will actually be saved. 53 if name is None: 54 name = content.name 55 name = self.get_available_name(name) 56 57 self._save(name, content) 58 59 # Store filenames with forward slashes, even on Windows 60 return force_unicode(name.replace('\\', '/')) 61 62 # These methods are part of the public API, with default implementations. 63 64 def get_valid_name(self, name): 65 """ 66 Returns a filename, based on the provided filename, that's suitable for 67 use in the target storage system. 68 """ 69 return get_valid_filename(name) 70 71 def get_available_name(self, name): 72 """ 73 Returns a filename that's free on the target storage system, and 74 available for new content to be written to. 75 """ 76 # If the filename already exists, keep adding an underscore to the name 77 # of the file until the filename doesn't exist. 78 while self.exists(name): 79 try: 80 dot_index = name.rindex('.') 81 except ValueError: # filename has no dot 82 name += '_' 83 else: 84 name = name[:dot_index] + '_' + name[dot_index:] 85 return name 86 87 def path(self, name): 88 """ 89 Returns a local filesystem path where the file can be retrieved using 90 Python's built-in open() function. Storage systems that can't be 91 accessed using open() should *not* implement this method. 92 """ 93 raise NotImplementedError("This backend doesn't support absolute paths.") 94 95 # The following methods form the public API for storage systems, but with 96 # no default implementations. Subclasses must implement *all* of these. 97 98 def delete(self, name): 99 """ 100 Deletes the specified file from the storage system. 101 """ 102 raise NotImplementedError() 103 104 def exists(self, name): 105 """ 106 Returns True if a file referened by the given name already exists in the 107 storage system, or False if the name is available for a new file. 108 """ 109 raise NotImplementedError() 110 111 def listdir(self, path): 112 """ 113 Lists the contents of the specified path, returning a 2-tuple of lists; 114 the first item being directories, the second item being files. 115 """ 116 raise NotImplementedError() 117 118 def size(self, name): 119 """ 120 Returns the total size, in bytes, of the file specified by name. 121 """ 122 raise NotImplementedError() 123 124 def url(self, name): 125 """ 126 Returns an absolute URL where the file's contents can be accessed 127 directly by a web browser. 128 """ 129 raise NotImplementedError() 130 131 class FileSystemStorage(StorageBase): 132 """ 133 Standard filesystem storage 134 """ 135 136 def __init__(self, location=settings.MEDIA_ROOT, base_url=settings.MEDIA_URL): 137 self.location = os.path.abspath(location) 138 self.base_url = base_url 139 140 def _open(self, name, mode='rb'): 141 return File(python_open(self.path(name), mode)) 142 143 def _save(self, name, content): 144 full_path = self.path(name) 145 146 directory = os.path.dirname(full_path) 147 if not os.path.exists(directory): 148 os.makedirs(directory) 149 elif not os.path.isdir(directory): 150 raise IOError("%s exists and is not a directory." % directory) 151 152 if hasattr(content, 'temporary_file_path'): 153 # This file has a file path that we can move. 154 content.close() 155 file_move_safe(content.temporary_file_path(), full_path) 156 else: 157 # This is a normal uploadedfile that we can stream. 158 fp = python_open(full_path, 'wb') 159 locks.lock(fp, locks.LOCK_EX) 160 for chunk in content.chunks(): 161 fp.write(chunk) 162 locks.unlock(fp) 163 fp.close() 164 165 def delete(self, name): 166 name = self.path(name) 167 # If the file exists, delete it from the filesystem. 168 if os.path.exists(name): 169 os.remove(name) 170 171 def exists(self, name): 172 return os.path.exists(self.path(name)) 173 174 def listdir(self, path): 175 path = self.path(path) 176 directories, files = [], [] 177 for entry in os.listdir(path): 178 if os.path.isdir(os.path.join(path, entry)): 179 directories.append(entry) 180 else: 181 files.append(entry) 182 return directories, files 183 184 def path(self, name): 185 try: 186 path = safe_join(self.location, name) 187 except ValueError: 188 raise SuspiciousOperation("Attempted access to '%s' denied." % name) 189 return os.path.normpath(path) 190 191 def size(self, name): 192 return os.path.getsize(self.path(name)) 193 194 def url(self, name): 195 if self.base_url is None: 196 raise ValueError("This file is not accessible via a URL.") 197 return urlparse.urljoin(self.base_url, name).replace('\\', '/') 198 199 class StorageFile(File): 200 def __init__(self, reference): 201 self.reference = reference 202 self.open() 203 204 def open(self): 205 if self.closed: 206 self.closed = False 207 self.seek(0) 208 209 def seek(self, position): 210 self.position = position 211 212 def tell(self): 213 return self.position 214 215 def read(self, num_bytes=None): 216 raise NotImplementedError("") 217 218 def write(self, content): 219 raise NotImplementedError("") 220 221 def close(self): 222 self._closed = True 223 224 def get_storage_class(import_path): 225 try: 226 dot = import_path.rindex('.') 227 except ValueError: 228 raise ImproperlyConfigured("%s isn't a storage module." % import_path) 229 module, classname = import_path[:dot], import_path[dot+1:] 230 try: 231 mod = __import__(module, {}, {}, ['']) 232 except ImportError, e: 233 raise ImproperlyConfigured('Error importing storage module %s: "%s"' % (module, e)) 234 try: 235 return getattr(mod, classname) 236 except AttributeError: 237 raise ImproperlyConfigured('Storage module "%s" does not define a "%s" class.' % (module, classname)) 238 239 Storage = get_storage_class(settings.DEFAULT_FILE_STORAGE) 240 default_storage = Storage() 241 242 def open(path, mode='rb', storage=None, mixin=None): 243 """ 244 A more intelligent open() than the one that comes with Python, working with 245 various storage systems and providing a more fully-featured File object. 246 """ 247 if storage is None: 248 # In keeping Python's own open(), if no storage system is supplied, it 249 # looks at the local filesystem. Since FileSystemStorage protects from 250 # access outside of its base location, though, this needs to instantiate 251 # a storage object speifically for the target file. 252 storage = FileSystemStorage(location=os.path.dirname(path)) 253 return storage.open(path, mode, mixin=mixin) -
django/core/files/uploadedfile.py
10 10 from StringIO import StringIO 11 11 12 12 from django.conf import settings 13 from django.core.files.base import File 13 14 14 15 from django.core.files import temp as tempfile 15 16 … … 39 40 else: 40 41 return property(getter, setter) 41 42 42 class UploadedFile( object):43 class UploadedFile(File): 43 44 """ 44 45 A abstract uploaded file (``TemporaryUploadedFile`` and 45 46 ``InMemoryUploadedFile`` are the built-in concrete subclasses). … … 76 77 77 78 name = property(_get_name, _set_name) 78 79 79 def chunks(self, chunk_size=None):80 """81 Read the file and yield chucks of ``chunk_size`` bytes (defaults to82 ``UploadedFile.DEFAULT_CHUNK_SIZE``).83 """84 if not chunk_size:85 chunk_size = UploadedFile.DEFAULT_CHUNK_SIZE86 87 if hasattr(self, 'seek'):88 self.seek(0)89 # Assume the pointer is at zero...90 counter = self.size91 92 while counter > 0:93 yield self.read(chunk_size)94 counter -= chunk_size95 96 80 # Deprecated properties 97 81 filename = deprecated_property(old="filename", new="name") 98 82 file_name = deprecated_property(old="file_name", new="name") … … 108 92 return self.read() 109 93 data = property(_get_data) 110 94 111 def multiple_chunks(self, chunk_size=None):112 """113 Returns ``True`` if you can expect multiple chunks.114 115 NB: If a particular file representation is in memory, subclasses should116 always return ``False`` -- there's no good reason to read from memory in117 chunks.118 """119 if not chunk_size:120 chunk_size = UploadedFile.DEFAULT_CHUNK_SIZE121 return self.size > chunk_size122 123 95 # Abstract methods; subclasses *must* define read() and probably should 124 96 # define open/close. 125 97 def read(self, num_bytes=None): … … 131 103 def close(self): 132 104 pass 133 105 134 def xreadlines(self):135 return self136 137 def readlines(self):138 return list(self.xreadlines())139 140 def __iter__(self):141 # Iterate over this file-like object by newlines142 buffer_ = None143 for chunk in self.chunks():144 chunk_buffer = StringIO(chunk)145 146 for line in chunk_buffer:147 if buffer_:148 line = buffer_ + line149 buffer_ = None150 151 # If this is the end of a line, yield152 # otherwise, wait for the next round153 if line[-1] in ('\n', '\r'):154 yield line155 else:156 buffer_ = line157 158 if buffer_ is not None:159 yield buffer_160 161 106 # Backwards-compatible support for uploaded-files-as-dictionaries. 162 107 def __getitem__(self, key): 163 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 -
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 , ImageField16 from django.db.models.fields import AutoField 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 … … 463 464 return getattr(self, cachename) 464 465 465 466 def _get_FIELD_filename(self, field): 466 if getattr(self, field.attname): # Value is not blank. 467 return os.path.normpath(os.path.join(settings.MEDIA_ROOT, getattr(self, field.attname))) 468 return '' 467 warn("instance.get_%s_filename() is deprecated. Use instance.%s.path instead." % \ 468 (field.attname, field.attname), DeprecationWarning, stacklevel=3) 469 try: 470 return getattr(self, field.attname).path 471 except ValueError: 472 return '' 469 473 470 474 def _get_FIELD_url(self, field): 471 if getattr(self, field.attname): # Value is not blank. 472 import urlparse 473 return urlparse.urljoin(settings.MEDIA_URL, getattr(self, field.attname)).replace('\\', '/') 474 return '' 475 warn("instance.get_%s_url() is deprecated. Use instance.%s.url instead." % \ 476 (field.attname, field.attname), DeprecationWarning, stacklevel=3) 477 try: 478 return getattr(self, field.attname).url 479 except ValueError: 480 return '' 475 481 476 482 def _get_FIELD_size(self, field): 477 return os.path.getsize(self._get_FIELD_filename(field)) 483 warn("instance.get_%s_size() is deprecated. Use instance.%s.size instead." % \ 484 (field.attname, field.attname), DeprecationWarning, stacklevel=3) 485 return getattr(self, field.attname).size 478 486 479 def _save_FIELD_file(self, field, filename, raw_field, save=True): 480 # Create the upload directory if it doesn't already exist 481 directory = os.path.join(settings.MEDIA_ROOT, field.get_directory_name()) 482 if not os.path.exists(directory): 483 os.makedirs(directory) 484 elif not os.path.isdir(directory): 485 raise IOError('%s exists and is not a directory' % directory) 487 def _save_FIELD_file(self, field, filename, content, save=True): 488 warn("instance.save_%s_file() is deprecated. Use instance.%s.save() instead." % \ 489 (field.attname, field.attname), DeprecationWarning, stacklevel=3) 490 return getattr(self, field.attname).save(filename, content, save) 486 491 487 # Check for old-style usage (files-as-dictionaries). Warn here first488 # since there are multiple locations where we need to support both new489 # and old usage.490 if isinstance(raw_field, dict):491 import warnings492 warnings.warn(493 message = "Representing uploaded files as dictionaries is deprecated. Use django.core.files.uploadedfile.SimpleUploadedFile instead.",494 category = DeprecationWarning,495 stacklevel = 2496 )497 from django.core.files.uploadedfile import SimpleUploadedFile498 raw_field = SimpleUploadedFile.from_dict(raw_field)499 500 elif isinstance(raw_field, basestring):501 import warnings502 warnings.warn(503 message = "Representing uploaded files as strings is deprecated. Use django.core.files.uploadedfile.SimpleUploadedFile instead.",504 category = DeprecationWarning,505 stacklevel = 2506 )507 from django.core.files.uploadedfile import SimpleUploadedFile508 raw_field = SimpleUploadedFile(filename, raw_field)509 510 if filename is None:511 filename = raw_field.file_name512 513 filename = field.get_filename(filename)514 515 # If the filename already exists, keep adding an underscore to the name516 # of the file until the filename doesn't exist.517 while os.path.exists(os.path.join(settings.MEDIA_ROOT, filename)):518 try:519 dot_index = filename.rindex('.')520 except ValueError: # filename has no dot.521 filename += '_'522 else:523 filename = filename[:dot_index] + '_' + filename[dot_index:]524 525 # Save the file name on the object and write the file to disk.526 setattr(self, field.attname, filename)527 full_filename = self._get_FIELD_filename(field)528 if hasattr(raw_field, 'temporary_file_path'):529 # This file has a file path that we can move.530 raw_field.close()531 file_move_safe(raw_field.temporary_file_path(), full_filename)532 else:533 # This is a normal uploadedfile that we can stream.534 fp = open(full_filename, 'wb')535 locks.lock(fp, locks.LOCK_EX)536 for chunk in raw_field.chunks():537 fp.write(chunk)538 locks.unlock(fp)539 fp.close()540 541 # Save the width and/or height, if applicable.542 if isinstance(field, ImageField) and \543 (field.width_field or field.height_field):544 from django.utils.images import get_image_dimensions545 width, height = get_image_dimensions(full_filename)546 if field.width_field:547 setattr(self, field.width_field, width)548 if field.height_field:549 setattr(self, field.height_field, height)550 551 # Save the object because it has changed, unless save is False.552 if save:553 self.save()554 555 492 _save_FIELD_file.alters_data = True 556 493 557 494 def _get_FIELD_width(self, field): 558 return self._get_image_dimensions(field)[0] 495 warn("instance.get_%s_width() is deprecated. Use instance.%s.width instead." % \ 496 (field.attname, field.attname), DeprecationWarning, stacklevel=3) 497 return getattr(self, field.attname).width() 559 498 560 499 def _get_FIELD_height(self, field): 561 return self._get_image_dimensions(field)[1] 500 warn("instance.get_%s_height() is deprecated. Use instance.%s.height instead." % \ 501 (field.attname, field.attname), DeprecationWarning, stacklevel=3) 502 return getattr(self, field.attname).height() 562 503 563 def _get_image_dimensions(self, field):564 cachename = "__%s_dimensions_cache" % field.name565 if not hasattr(self, cachename):566 from django.utils.images import get_image_dimensions567 filename = self._get_FIELD_filename(field)568 setattr(self, cachename, get_image_dimensions(filename))569 return getattr(self, cachename)570 504 571 572 505 ############################################ 573 506 # HELPER FUNCTIONS (CURRIED MODEL METHODS) # 574 507 ############################################ -
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 … … 763 762 defaults.update(kwargs) 764 763 return super(EmailField, self).formfield(**defaults) 765 764 766 class FileField(Field):767 def __init__(self, verbose_name=None, name=None, upload_to='', **kwargs):768 self.upload_to = upload_to769 kwargs['max_length'] = kwargs.get('max_length', 100)770 Field.__init__(self, verbose_name, name, **kwargs)771 772 def get_internal_type(self):773 return "FileField"774 775 def get_db_prep_value(self, value):776 "Returns field's value prepared for saving into a database."777 # Need to convert UploadedFile objects provided via a form to unicode for database insertion778 if hasattr(value, 'name'):779 return value.name780 elif value is None:781 return None782 else:783 return unicode(value)784 785 def get_manipulator_fields(self, opts, manipulator, change, name_prefix='', rel=False, follow=True):786 field_list = Field.get_manipulator_fields(self, opts, manipulator, change, name_prefix, rel, follow)787 if not self.blank:788 if rel:789 # This validator makes sure FileFields work in a related context.790 class RequiredFileField(object):791 def __init__(self, other_field_names, other_file_field_name):792 self.other_field_names = other_field_names793 self.other_file_field_name = other_file_field_name794 self.always_test = True795 def __call__(self, field_data, all_data):796 if not all_data.get(self.other_file_field_name, False):797 c = validators.RequiredIfOtherFieldsGiven(self.other_field_names, ugettext_lazy("This field is required."))798 c(field_data, all_data)799 # First, get the core fields, if any.800 core_field_names = []801 for f in opts.fields:802 if f.core and f != self:803 core_field_names.extend(f.get_manipulator_field_names(name_prefix))804 # Now, if there are any, add the validator to this FormField.805 if core_field_names:806 field_list[0].validator_list.append(RequiredFileField(core_field_names, field_list[1].field_name))807 else:808 v = validators.RequiredIfOtherFieldNotGiven(field_list[1].field_name, ugettext_lazy("This field is required."))809 v.always_test = True810 field_list[0].validator_list.append(v)811 field_list[0].is_required = field_list[1].is_required = False812 813 # If the raw path is passed in, validate it's under the MEDIA_ROOT.814 def isWithinMediaRoot(field_data, all_data):815 f = os.path.abspath(os.path.join(settings.MEDIA_ROOT, field_data))816 if not f.startswith(os.path.abspath(os.path.normpath(settings.MEDIA_ROOT))):817 raise validators.ValidationError, _("Enter a valid filename.")818 field_list[1].validator_list.append(isWithinMediaRoot)819 return field_list820 821 def contribute_to_class(self, cls, name):822 super(FileField, self).contribute_to_class(cls, name)823 setattr(cls, 'get_%s_filename' % self.name, curry(cls._get_FIELD_filename, field=self))824 setattr(cls, 'get_%s_url' % self.name, curry(cls._get_FIELD_url, field=self))825 setattr(cls, 'get_%s_size' % self.name, curry(cls._get_FIELD_size, field=self))826 setattr(cls, 'save_%s_file' % self.name, lambda instance, filename, raw_field, save=True: instance._save_FIELD_file(self, filename, raw_field, save))827 dispatcher.connect(self.delete_file, signal=signals.post_delete, sender=cls)828 829 def delete_file(self, instance):830 if getattr(instance, self.attname):831 file_name = getattr(instance, 'get_%s_filename' % self.name)()832 # If the file exists and no other object of this type references it,833 # delete it from the filesystem.834 if os.path.exists(file_name) and \835 not instance.__class__._default_manager.filter(**{'%s__exact' % self.name: getattr(instance, self.attname)}):836 os.remove(file_name)837 838 def get_manipulator_field_objs(self):839 return [oldforms.FileUploadField, oldforms.HiddenField]840 841 def get_manipulator_field_names(self, name_prefix):842 return [name_prefix + self.name + '_file', name_prefix + self.name]843 844 def save_file(self, new_data, new_object, original_object, change, rel, save=True):845 upload_field_name = self.get_manipulator_field_names('')[0]846 if new_data.get(upload_field_name, False):847 if rel:848 file = new_data[upload_field_name][0]849 else:850 file = new_data[upload_field_name]851 852 if not file:853 return854 855 # Backwards-compatible support for files-as-dictionaries.856 # We don't need to raise a warning because Model._save_FIELD_file will857 # do so for us.858 try:859 file_name = file.name860 except AttributeError:861 file_name = file['filename']862 863 func = getattr(new_object, 'save_%s_file' % self.name)864 func(file_name, file, save)865 866 def get_directory_name(self):867 return os.path.normpath(force_unicode(datetime.datetime.now().strftime(smart_str(self.upload_to))))868 869 def get_filename(self, filename):870 from django.utils.text import get_valid_filename871 f = os.path.join(self.get_directory_name(), get_valid_filename(os.path.basename(filename)))872 return os.path.normpath(f)873 874 def save_form_data(self, instance, data):875 from django.core.files.uploadedfile import UploadedFile876 if data and isinstance(data, UploadedFile):877 getattr(instance, "save_%s_file" % self.name)(data.name, data, save=False)878 879 def formfield(self, **kwargs):880 defaults = {'form_class': forms.FileField}881 # If a file has been provided previously, then the form doesn't require882 # that a new file is provided this time.883 # The code to mark the form field as not required is used by884 # form_for_instance, but can probably be removed once form_for_instance885 # is gone. ModelForm uses a different method to check for an existing file.886 if 'initial' in kwargs:887 defaults['required'] = False888 defaults.update(kwargs)889 return super(FileField, self).formfield(**defaults)890 891 765 class FilePathField(Field): 892 766 def __init__(self, verbose_name=None, name=None, path='', match=None, recursive=False, **kwargs): 893 767 self.path, self.match, self.recursive = path, match, recursive … … 929 803 defaults.update(kwargs) 930 804 return super(FloatField, self).formfield(**defaults) 931 805 932 class ImageField(FileField):933 def __init__(self, verbose_name=None, name=None, width_field=None, height_field=None, **kwargs):934 self.width_field, self.height_field = width_field, height_field935 FileField.__init__(self, verbose_name, name, **kwargs)936 937 def get_manipulator_field_objs(self):938 return [oldforms.ImageUploadField, oldforms.HiddenField]939 940 def contribute_to_class(self, cls, name):941 super(ImageField, self).contribute_to_class(cls, name)942 # Add get_BLAH_width and get_BLAH_height methods, but only if the943 # image field doesn't have width and height cache fields.944 if not self.width_field:945 setattr(cls, 'get_%s_width' % self.name, curry(cls._get_FIELD_width, field=self))946 if not self.height_field:947 setattr(cls, 'get_%s_height' % self.name, curry(cls._get_FIELD_height, field=self))948 949 def save_file(self, new_data, new_object, original_object, change, rel, save=True):950 FileField.save_file(self, new_data, new_object, original_object, change, rel, save)951 # If the image has height and/or width field(s) and they haven't952 # changed, set the width and/or height field(s) back to their original953 # values.954 if change and (self.width_field or self.height_field) and save:955 if self.width_field:956 setattr(new_object, self.width_field, getattr(original_object, self.width_field))957 if self.height_field:958 setattr(new_object, self.height_field, getattr(original_object, self.height_field))959 new_object.save()960 961 def formfield(self, **kwargs):962 defaults = {'form_class': forms.ImageField}963 defaults.update(kwargs)964 return super(ImageField, self).formfield(**defaults)965 966 806 class IntegerField(Field): 967 807 empty_strings_allowed = False 968 808 def get_db_prep_value(self, value): -
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.core.files.uploadedfile import UploadedFile 10 from django.utils.functional import curry 11 from django.dispatch import dispatcher 12 from django.db.models import signals 13 from django.utils.encoding import force_unicode, smart_str 14 from django.utils.translation import ugettext_lazy, ugettext as _ 15 from django import oldforms 16 from django import forms 17 from django.core import validators 18 from django.db.models.loading import cache 19 20 class FieldFile(File): 21 def __init__(self, instance, field, name): 22 self.instance = instance 23 self.field = field 24 self.storage = field.storage 25 self._name = name or u'' 26 self._closed = False 27 28 def __eq__(self, other): 29 # Older code may be expecting FileField values to be simple strings. 30 # By overriding the == operator, it can remain backwards compatibility. 31 if hasattr(other, 'name'): 32 return self.name == other.name 33 return self.name == other 34 35 # The standard File contains most of the necessary properties, but 36 # FieldFiles can be instantiated without a name, so that needs to 37 # be checked for here. 38 39 def _require_file(self): 40 if not self: 41 raise ValueError("The '%s' attribute has no file associated with it." % self.field.name) 42 43 def _get_file(self): 44 self._require_file() 45 if not hasattr(self, '_file'): 46 self._file = self.storage.open(self.name, 'rb') 47 return self._file 48 file = property(_get_file) 49 50 def _get_path(self): 51 self._require_file() 52 return self.storage.path(self.name) 53 path = property(_get_path) 54 55 def _get_url(self): 56 self._require_file() 57 return self.storage.url(self.name) 58 url = property(_get_url) 59 60 def open(self, mode='rb'): 61 self._require_file() 62 return super(FieldFile, self).open(mode) 63 # open() doesn't alter the file's contents, but it does reset the pointer 64 open.alters_data = True 65 66 # In addition to the standard File API, FieldFiles have extra methods 67 # to further manipulate the underlying file, as well as update the 68 # associated model instance. 69 70 def save(self, name, content, save=True): 71 name = self.field.generate_filename(self.instance, name) 72 self._name = self.storage.save(name, content) 73 setattr(self.instance, self.field.name, self.name) 74 75 # Update the filesize cache 76 self._size = len(content) 77 78 # Save the object because it has changed, unless save is False 79 if save: 80 self.instance.save() 81 save.alters_data = True 82 83 def delete(self, save=True): 84 self.close() 85 self.storage.delete(self.name) 86 87 self._name = None 88 setattr(self.instance, self.field.name, self.name) 89 90 # Delete the filesize cache 91 if hasattr(self, '_size'): 92 del self._size 93 94 if save: 95 self.instance.save() 96 delete.alters_data = True 97 98 def __getstate__(self): 99 # FieldFile needs access to its associated model field and an instance 100 # it's attached to in order to work properly, but the only necessary 101 # data to be pickled is the file's name itself. Everything else will 102 # be restored later, by FileDescriptor below. 103 return {'_name': self.name, '_closed': False} 104 105 class FileDescriptor(object): 106 def __init__(self, field): 107 self.field = field 108 109 def __get__(self, instance=None, owner=None): 110 if instance is None: 111 raise AttributeError, "%s can only be accessed from %s instances." % (self.field.name(self.owner.__name__)) 112 file = instance.__dict__[self.field.name] 113 if not isinstance(file, FieldFile): 114 # Create a new instance of FieldFile, based on a given file name 115 instance.__dict__[self.field.name] = self.field.attr_class(instance, self.field, file) 116 elif not hasattr(file, 'field'): 117 # The FieldFile was pickled, so some attributes need to be reset. 118 file.instance = instance 119 file.field = self.field 120 file.storage = self.field.storage 121 return instance.__dict__[self.field.name] 122 123 def __set__(self, instance, value): 124 instance.__dict__[self.field.name] = value 125 126 class FileField(Field): 127 attr_class = FieldFile 128 129 def __init__(self, verbose_name=None, name=None, upload_to='', storage=None, **kwargs): 130 for arg in ('core', 'primary_key', 'unique'): 131 if arg in kwargs: 132 raise TypeError("'%s' is not a valid argument for %s." % (arg, self.__class__)) 133 134 self.storage = storage or default_storage 135 self.upload_to = upload_to 136 if callable(upload_to): 137 self.generate_filename = upload_to 138 139 kwargs['max_length'] = kwargs.get('max_length', 100) 140 super(FileField, self).__init__(verbose_name, name, **kwargs) 141 142 def get_internal_type(self): 143 return "FileField" 144 145 def get_db_prep_lookup(self, lookup_type, value): 146 if hasattr(value, 'name'): 147 value = value.name 148 return super(FileField, self).get_db_prep_lookup(lookup_type, value) 149 150 def get_db_prep_value(self, value): 151 "Returns field's value prepared for saving into a database." 152 # Need to convert File objects provided via a form to unicode for database insertion 153 if value is None: 154 return None 155 return unicode(value.name) 156 157 def get_manipulator_fields(self, opts, manipulator, change, name_prefix='', rel=False, follow=True): 158 field_list = Field.get_manipulator_fields(self, opts, manipulator, change, name_prefix, rel, follow) 159 if not self.blank: 160 if rel: 161 # This validator makes sure FileFields work in a related context. 162 class RequiredFileField(object): 163 def __init__(self, other_field_names, other_file_field_name): 164 self.other_field_names = other_field_names 165 self.other_file_field_name = other_file_field_name 166 self.always_test = True 167 def __call__(self, field_data, all_data): 168 if not all_data.get(self.other_file_field_name, False): 169 c = validators.RequiredIfOtherFieldsGiven(self.other_field_names, ugettext_lazy("This field is required.")) 170 c(field_data, all_data) 171 # First, get the core fields, if any. 172 core_field_names = [] 173 for f in opts.fields: 174 if f.core and f != self: 175 core_field_names.extend(f.get_manipulator_field_names(name_prefix)) 176 # Now, if there are any, add the validator to this FormField. 177 if core_field_names: 178 field_list[0].validator_list.append(RequiredFileField(core_field_names, field_list[1].field_name)) 179 else: 180 v = validators.RequiredIfOtherFieldNotGiven(field_list[1].field_name, ugettext_lazy("This field is required.")) 181 v.always_test = True 182 field_list[0].validator_list.append(v) 183 field_list[0].is_required = field_list[1].is_required = False 184 185 # If the raw path is passed in, validate it's under the MEDIA_ROOT. 186 def isWithinMediaRoot(field_data, all_data): 187 f = os.path.abspath(os.path.join(settings.MEDIA_ROOT, field_data)) 188 if not f.startswith(os.path.abspath(os.path.normpath(settings.MEDIA_ROOT))): 189 raise validators.ValidationError(_("Enter a valid filename.")) 190 field_list[1].validator_list.append(isWithinMediaRoot) 191 return field_list 192 193 def contribute_to_class(self, cls, name): 194 super(FileField, self).contribute_to_class(cls, name) 195 setattr(cls, self.name, FileDescriptor(self)) 196 setattr(cls, 'get_%s_filename' % self.name, curry(cls._get_FIELD_filename, field=self)) 197 setattr(cls, 'get_%s_url' % self.name, curry(cls._get_FIELD_url, field=self)) 198 setattr(cls, 'get_%s_size' % self.name, curry(cls._get_FIELD_size, field=self)) 199 setattr(cls, 'save_%s_file' % self.name, lambda instance, name, content, save=True: instance._save_FIELD_file(self, name, content, save)) 200 dispatcher.connect(self.delete_file, signal=signals.post_delete, sender=cls) 201 202 def delete_file(self, instance, sender): 203 file = getattr(instance, self.attname) 204 # If no other object of this type references the file, 205 # and it's not the default value for future objects, 206 # delete it from the backend. 207 if file and file.name != self.default and \ 208 not sender._default_manager.filter(**{self.name: file.name}): 209 file.delete(save=False) 210 elif file: 211 # Otherwise, just close the file, so it doesn't tie up resources. 212 file.close() 213 214 def get_manipulator_field_objs(self): 215 return [oldforms.FileUploadField, oldforms.HiddenField] 216 217 def get_manipulator_field_names(self, name_prefix): 218 return [name_prefix + self.name + '_file', name_prefix + self.name] 219 220 def save_file(self, new_data, new_object, original_object, change, rel, save=True): 221 upload_field_name = self.get_manipulator_field_names('')[0] 222 if new_data.get(upload_field_name, False): 223 if rel: 224 file = new_data[upload_field_name][0] 225 else: 226 file = new_data[upload_field_name] 227 228 # Backwards-compatible support for files-as-dictionaries. 229 # We don't need to raise a warning because the storage backend will 230 # do so for us. 231 try: 232 filename = file.name 233 except AttributeError: 234 filename = file['filename'] 235 filename = self.get_filename(filename) 236 237 getattr(new_object, self.attname).save(filename, file, save) 238 239 def get_directory_name(self): 240 return os.path.normpath(force_unicode(datetime.datetime.now().strftime(smart_str(self.upload_to)))) 241 242 def get_filename(self, filename): 243 return os.path.normpath(self.storage.get_valid_name(os.path.basename(filename))) 244 245 def generate_filename(self, instance, filename): 246 return os.path.join(self.get_directory_name(), self.get_filename(filename)) 247 248 def save_form_data(self, instance, data): 249 if data and isinstance(data, UploadedFile): 250 getattr(instance, self.name).save(data.name, data, save=False) 251 252 def formfield(self, **kwargs): 253 defaults = {'form_class': forms.FileField} 254 # If a file has been provided previously, then the form doesn't require 255 # that a new file is provided this time. 256 # The code to mark the form field as not required is used by 257 # form_for_instance, but can probably be removed once form_for_instance 258 # is gone. ModelForm uses a different method to check for an existing file. 259 if 'initial' in kwargs: 260 defaults['required'] = False 261 defaults.update(kwargs) 262 return super(FileField, self).formfield(**defaults) 263 264 class ImageFieldFile(ImageFile, FieldFile): 265 def save(self, name, content, save=True): 266 super(ImageFieldFile, self).save(name, content, save) 267 268 # Update the cache for image dimensions 269 from django.core.files.images import get_image_dimensions 270 if not hasattr(content, 'read'): 271 content = ContentFile(name, content) 272 self._dimensions_cache = get_image_dimensions(content) 273 274 def delete(self, save=True): 275 # Clear the image dimensions cache 276 if hasattr(self, '_dimensions_cache'): 277 del self._dimensions_cache 278 279 super(ImageFieldFile, self).delete(save) 280 281 class ImageField(FileField): 282 attr_class = ImageFieldFile 283 284 def __init__(self, verbose_name=None, name=None, width_field=None, height_field=None, **kwargs): 285 self.width_field, self.height_field = width_field, height_field 286 FileField.__init__(self, verbose_name, name, **kwargs) 287 288 def get_manipulator_field_objs(self): 289 return [oldforms.ImageUploadField, oldforms.HiddenField] 290 291 def contribute_to_class(self, cls, name): 292 super(ImageField, self).contribute_to_class(cls, name) 293 # Add get_BLAH_width and get_BLAH_height methods, but only if the 294 # image field doesn't have width and height cache fields. 295 if not self.width_field: 296 setattr(cls, 'get_%s_width' % self.name, curry(cls._get_FIELD_width, field=self)) 297 if not self.height_field: 298 setattr(cls, 'get_%s_height' % self.name, curry(cls._get_FIELD_height, field=self)) 299 300 def save_form_data(self, instance, data): 301 # If the image has height and/or width field(s) and they haven't 302 # changed, set the width and/or height field(s) back to their original 303 # values. 304 if self.width_field or self.height_field: 305 if original_object and not change: 306 if self.width_field: 307 setattr(new_object, self.width_field, getattr(original_object, self.width_field)) 308 if self.height_field: 309 setattr(new_object, self.height_field, getattr(original_object, self.height_field)) 310 else: 311 from django.utils.images import get_image_dimensions 312 313 upload_field_name = self.get_manipulator_field_names('')[0] 314 if rel: 315 file = new_data[upload_field_name][0] 316 else: 317 file = new_data[upload_field_name] 318 319 # Get the width and height from the raw content to avoid extra 320 # unnecessary trips to the file backend. 321 width, height = get_image_dimensions(file) 322 323 if self.width_field: 324 setattr(new_object, self.width_field, width) 325 if self.height_field: 326 setattr(new_object, self.height_field, height) 327 super(ImageField, self).save_form_data(instance, data) 328 329 def formfield(self, **kwargs): 330 defaults = {'form_class': forms.ImageField} 331 defaults.update(kwargs) 332 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) -
docs/custom_model_fields.txt
596 596 instance, not a ``HandField``). So if your ``__unicode__()`` method 597 597 automatically converts to the string form of your Python object, you can 598 598 save yourself a lot of work. 599 600 Writing a ``FileField`` subclass 601 ================================= 602 603 In addition to the above methods, fields that deal with files have a few other 604 special requirements which must be taken into account. The majority of the 605 mechanics provided by ``FileField``, such as controlling database storage and 606 retrieval, can remain unchanged, leaving subclasses to deal with the challenge 607 of supporting a particular type of file. 608 609 Django provides a ``File`` class, which is used as a proxy to the file's 610 contents and operations. This can be subclassed to customzie hwo the file is 611 accessed, and what methods are available. It lives at 612 ``django.db.models.fields.files``, and its default behavior is explained in the 613 `file documentation`_. 614 615 Once a subclass of ``File`` is created, the new ``FileField`` subclass must be 616 told to use it. To do so, simply assign the new ``File`` subclass to the special 617 ``attr_class`` attribute of the ``FileField`` subclass. 618 619 .. _file documentation: ../files/ 620 621 A few suggestions 622 ------------------ 623 624 In addition to the above details, there are a few guidelines which can greatly 625 improve the efficiency and readability of the field's code. 626 627 1. The source for Django's own ``ImageField`` (in 628 ``django/db/models/fields/files.py``) is a great example of how to 629 subclass ``FileField`` to support a particular type of file, as it 630 incorporates all of the techniques described above. 631 632 2. Cache file attributes wherever possible. Since files may be stored in 633 remote storage systems, retrieving them may cost extra time, or even 634 money, that isn't always necessary. Once a file is retrieved to obtain 635 some data about its content, cache as much of that data as possible to 636 reduce the number of times the file must be retrieved on subsequent 637 calls for that information. -
docs/db-api.txt
2298 2298 get_FOO_filename() 2299 2299 ------------------ 2300 2300 2301 **Deprecated in Django development version. See `managing files`_ for the new, 2302 preferred method for dealing with files.** 2303 2301 2304 For every ``FileField``, the object will have a ``get_FOO_filename()`` method, 2302 2305 where ``FOO`` is the name of the field. This returns the full filesystem path 2303 2306 to the file, according to your ``MEDIA_ROOT`` setting. … … 2313 2316 get_FOO_url() 2314 2317 ------------- 2315 2318 2319 **Deprecated in Django development version. See `managing files`_ for the new, 2320 preferred method for dealing with files.** 2321 2316 2322 For every ``FileField``, the object will have a ``get_FOO_url()`` method, 2317 2323 where ``FOO`` is the name of the field. This returns the full URL to the file, 2318 2324 according to your ``MEDIA_URL`` setting. If the value is blank, this method … … 2326 2332 get_FOO_size() 2327 2333 -------------- 2328 2334 2335 **Deprecated in Django development version. See `managing files`_ for the new, 2336 preferred method for dealing with files.** 2337 2329 2338 For every ``FileField``, the object will have a ``get_FOO_size()`` method, 2330 2339 where ``FOO`` is the name of the field. This returns the size of the file, in 2331 2340 bytes. (Behind the scenes, it uses ``os.path.getsize``.) … … 2333 2342 save_FOO_file(filename, raw_contents) 2334 2343 ------------------------------------- 2335 2344 2345 **Deprecated in Django development version. See `managing files`_ for the new, 2346 preferred method for dealing with files.** 2347 2336 2348 For every ``FileField``, the object will have a ``save_FOO_file()`` method, 2337 2349 where ``FOO`` is the name of the field. This saves the given file to the 2338 2350 filesystem, using the given filename. If a file with the given filename already … … 2342 2354 get_FOO_height() and get_FOO_width() 2343 2355 ------------------------------------ 2344 2356 2357 **Deprecated in Django development version. See `managing files`_ for the new, 2358 preferred method for dealing with files.** 2359 2345 2360 For every ``ImageField``, the object will have ``get_FOO_height()`` and 2346 2361 ``get_FOO_width()`` methods, where ``FOO`` is the name of the field. This 2347 2362 returns the height (or width) of the image, as an integer, in pixels. 2348 2363 2364 .. _`managing files`: ../files/ 2365 2349 2366 Shortcuts 2350 2367 ========= 2351 2368 -
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 The ``File`` object 14 =================== 15 16 Any time Django references a file, it will be an instance of the `File` class, 17 living at `django.core.files`, or one of its subclasses. This provides many of 18 the same features as Python's own `file object`_, but has a few additions and 19 is customized for working with large-scale applications. 20 21 .. _file object: http://docs.python.org/lib/bltin-file-objects.html 22 23 Example 24 ------- 25 26 The simplest way to get access to a `File` is to use Django's drop-in 27 replacement for Python's built-in `open()`, located at django.core.files:: 28 29 >>> from django.core.files import open 30 31 >>> writable = open('/tmp/hello_world', 'w') 32 >>> writable.name, writable.mode 33 ('/tmp/hello_world', 'w') 34 >>> writable.write('Hello, world!') 35 >>> writable.close() 36 37 >>> readable = open('/tmp/hello_world') 38 >>> readable.size 39 13 40 >>> readable.close() 41 42 ``path`` 43 -------- 44 45 Returns the absolute path to the file's location on a local filesystem. For 46 storage systems which do not store files locally, this will return `None`. 47 48 ``url`` 49 ------- 50 51 Provides a URL where the content of the file can be retrieved. Therefore, 52 returned from this method is suitable for use as the destination of a link to 53 the file. 54 55 ``size`` 56 -------- 57 58 Returns the size of the file, as an integer. 59 60 ``open(mode='rb')`` 61 ------------------- 62 63 Re-opens the file, resetting the internal pointer back to the beginning. The 64 ``mode`` argument allows the same values as Python's standard ``open()``, and 65 overrides whatever mode the file was originally opened with. 66 67 ``read(num_bytes=None)`` 68 ------------------------ 69 70 Retrieves some content from the file, returning it as a string. The optional 71 ``size`` is the number of bytes to read; if not specified, the file will be read 72 through to the end. 73 74 ``__iter__()`` 75 -------------- 76 77 Iterates over the lines in the file, preserving newline characters on each line. 78 This allows the file to be used in simple loops, using ``for line in file``. 79 80 ``chunks(chunk_size=None)`` 81 --------------------------- 82 83 Yields the contents of the file in smaller chunks, that can be looped over to 84 access the file without loading it all into memory at once. If ``chunk_size`` 85 isn't provided, it defaults to 64 KB. 86 87 ``multiple_chunks(chunk_size=None)`` 88 ------------------------------------ 89 90 Returns ``True`` if the file is large enough to require multiple chunks to 91 access all of its content, or ``False`` if it can all be read in one pass. The 92 optional ``chunk_size`` works the same as in ``chunks()`` above. 93 94 ``write(content)`` 95 ------------------ 96 97 Writes the specified content string to the file. Depending on the storage system 98 behind the scenes, this content might not be fully committed until ``close()`` 99 is called on the file. 100 101 ``close()`` 102 ----------- 103 104 Closes the file, so it can't be read from or written to anymore. If there's 105 still any content that hasn't been written to the file itself, this will commit 106 that as well. 107 108 ``ImageFile`` 109 ============= 110 111 Anywhere Django can open a new file, it also accepts a mixin class to support 112 more specific file types. For images, there's a more specific ``ImageFile``, 113 available from ``django.core.files.images``. 114 115 ``width and height`` 116 -------------------- 117 118 When using an ``ImageField``, these two attributes will be available, providing 119 easy access to the dimensions of the image. 120 121 Using files in models 122 ===================== 123 124 When accessing a ``FileField`` attached to a model, a special object provides 125 access to the file and information about it. 126 127 Example 128 ------- 129 130 Consider the following model, using an ``ImageField`` to store a product photo:: 131 132 class Product(models.Model): 133 name = models.CharField(maxlength=255) 134 price = models.DecimalField(max_digits=5, decimal_places=2) 135 photo = models.ImageField(upload_to='product_photos') 136 137 Your views can then use the ``photo`` attribute with the functions described 138 above, as follows:: 139 140 >>> car = Product.object.get(name="'57 Chevy") 141 >>> car.photo 142 <ImageFieldFile: 123.jpg> 143 >>> car.photo.url 144 '/products/photo/123.jpg' 145 >>> car.photo.width, car.photo.height 146 (800, 600) 147 148 ``save(name, content, save=True)`` 149 ---------------------------------- 150 151 Saves a new file with the filename and contents provided. This will not replace 152 the existing file, but will create a new file and update the object to point to 153 it. The optional ``save`` argument dictates whether the model instance will be 154 saved to the database immediately. 155 156 ``delete(save=True)`` 157 --------------------- 158 159 Removes the file from the model instance and deletes it from the underlying 160 storage system. The optional ``save`` argument indicates whether the model 161 instance will saved to the database immediately. 162 163 Using a storage system with FileField 164 ===================================== 165 166 When using a storage system, supply whatever options are appropriate for 167 that system when creating a new object. Then pass that object as the ``storage`` 168 argument to a ``FileField``. Details on the requirements for the included 169 storage system can be found below. 170 171 If using the default storage system, it is not necessary to create a storage 172 object explicitly. In this case, the ``FileField`` will use the one referenced 173 by the `DEFAULT_FILE_STORAGE setting`_. 174 175 See the `FileField documentation`_ for more information on using the field. 176 177 .. _DEFAULT_FILE_STORAGE setting: ../settings/#default-file-storage 178 .. _FileField documentation: ../model-api/#filefield 179 180 For example, the following code will explicitly use the ``FileSystemStorage``:: 181 182 from django.db import models 183 from django.core.files.storage import FileSystemStorage 184 185 fs = FileSystemStorage(location='product_photos') 186 187 class Product(models.Model): 188 name = models.CharField(maxlength=255) 189 price = models.DecimalField(max_digits=5, decimal_places=2) 190 photo = models.ImageField(storage=fs) 191 192 Using a storage system on its own 193 ================================= 194 195 Storage systems may also be used directly, without being attached to a model. 196 Simply use the following API on any instantiated storage system to access files 197 without having to worry about the underlying mechanism. In addition to explicit 198 storage mechanisms, the file storage module, ``django.core.files.storage``, 199 exports a ``default_storage`` object that's automatically created from the 200 ``DEFAULT_FILE_STORAGE`` setting:: 201 202 >>> from django.core.files.storage import default_storage 203 204 With a functional storage system on hand, managing files is quite simple, with a 205 few basic methods to handle the most common operations:: 206 207 >>> path = storage.save('/path/to/file', 'new content') 208 >>> path 209 u'/path/to/file' 210 >>> storage.filesize(path) 211 11 212 >>> storage.open(path).read() 213 'new content' 214 >>> storage.delete(path) 215 >>> storage.exists(path) 216 False 217 218 ``exists(name)`` 219 ---------------- 220 221 Returns ``True`` or ``False, indicating whether there is already a file present 222 at the location referenced by``name``. 223 224 ``path(name)`` 225 -------------- 226 227 Returns the local filesystem path where the file can be opened using Python's 228 standard ``open()``. For storage systems that aren't accessible from the local 229 filesystem, this will raise ``NotImplementedError`` instead. 230 231 ``size(name)`` 232 -------------- 233 234 Returns the total size, in bytes, of the file referenced by ``name``. 235 236 ``url(name)`` 237 ------------- 238 239 Returns the URL where the contents of the file referenced by ``name`` can be 240 accessed. 241 242 ``open(name, mode='rb', mixin=None)`` 243 ------------------------------------- 244 245 Returns an open file, or file-like, object to provide access to the contents of 246 the file referenced by ``name``. The ``mode`` argument allows the same values as 247 Python's standard ``open()`` function. The ``mixin`` is an optional class that, 248 if provided, will be applied to the ``File`` object returned from this method. 249 250 ``save(name, content)`` 251 ----------------------- 252 253 Saves a new file using the storage system, preferably with the name specified. 254 If there already exists a file at the location referenced by ``name``, this may 255 modify the filename as necessary to locate one that is available. Once the file 256 is saved, this method will return the filename where the file was actually 257 stored. 258 259 ``delete(name)`` 260 ---------------- 261 262 Deletes the file referenced by ``name``. If the file does not already exist, 263 this method will simply return without raising an exception. 264 265 Available storage systems 266 ========================= 267 268 Only one storage system is supplied in the official Django distribution, but 269 more may be available elsewhere. If you'd like to use a different storage system 270 than the one listed below, see the documentation included with it. 271 272 ``django.core.files.storage.FileSystemStorage`` 273 ----------------------------------------------- 274 275 This simply stores files on the system's standard filesystem. 276 277 ====================== =================================================== 278 Argument Description 279 ====================== =================================================== 280 ``location`` Optional. Absolute path to the directory that will 281 hold the files. If omitted, it will be set to the 282 value of your ``MEDIA_ROOT`` setting. 283 ``base_url`` Optional. URL that serves the files stored at this 284 location. If omitted, it will default to the value 285 of your ``MEDIA_URL`` setting. 286 ====================== =================================================== 287 288 Writing a storage system 289 ======================== 290 291 While the default filesystem storage is suitable for most needs, there are many 292 other storage mechanisms that may be used, and situations that will require 293 special processing. In order to use Django in these environments, it's fairly 294 simple to write a new storage system, creating a wrapper around whatever 295 libraries are used to access your files, or simply customizing method calls on 296 an existing storage class. 297 298 If a storage system requires any configuration options to determine how it 299 should access the underlying storage mechanism or cusotmize its behavior in 300 other ways, those options should be specified in a particular way. Because the 301 default storage system is specified as a string, Django must be able to 302 instantiate it without any arguments, and any required arguments should be 303 specified as global settings, which can be referenced from the storage system. 304 For example:: 305 306 from django.conf import settings 307 from django.core.files.storage import Storage 308 309 class CustomStorage(Storage): 310 def __init__(self, option=settings.CUSTOM_STORAGE_OPTION): 311 ... 312 313 Every storage system will have all the methods described above, but there are a 314 few with have default behaviors that shouldn't be overridden by these subclasses 315 in most situations. Each of these has a different set of responsibilities that 316 the storage system is expected to fulfill: 317 318 * ``path()`` -- unless the class provides access to files that are also 319 accessible via the local filesystem, this should inherit the default behavior 320 of raising a ``NotImplementedError``. For those that do represent portions of 321 the filesystem, subclassing ``FileSystemStorage`` will typically be more 322 appropriate anyway. 323 324 * ``open()`` -- This provides some additional logic that isn't specific to 325 file retrieval, by supporting the ``mixin`` argument. Instead of overriding 326 this directly, storage systems should provide an ``_open()`` method as 327 described below. 328 329 * ``save()`` -- The ``name`` provided to this is actually more a preference, 330 because it will actually go through both ``get_valid_name()`` and 331 ``get_available_name()`` to determine what name the will actually be given. 332 It also returns the final name, taking care to adjust it to Unix-style paths. 333 Since these features aren't related to actually storing the file, subclasses 334 should instead provide a ``_save()`` method as described below. 335 336 The default beaviors for these methods are provided by the provided ``Storage`` 337 class, living at ``django.files.storage``. In addition, the two other methods 338 used by ``save()`` internally to determine the final filename, which have 339 default implementations, but can be overridden, and there are two other methods 340 that must be provided for all storage systems. 341 342 ``get_valid_name(name)`` 343 ------------------------ 344 345 Returns a filename suitable for use with the underlying storage system. The 346 ``name`` argument passed to this method is the original filename sent to the 347 server, after having any path information removed. Override this to customize 348 how non-standard characters are converted to safe filenames. 349 350 The code provided on ``Storage`` retains only alpha-numeric characters, periods 351 and underscores from the original filename, removing everything else. 352 353 ``get_available_name(name)`` 354 ---------------------------- 355 356 Returns a filename that is available in the storage mechanism, possibly taking 357 the provided filename into account. The ``name`` argument passed to this method 358 will have already cleaned to a filename valid for the storage system, according 359 to the ``get_valid_name()`` method described above. 360 361 The code provided on ``Storage`` simply appends underscores to the filename 362 until it finds one that's available in the destination directory. 363 364 ``_open(name, mode='rb')`` 365 -------------------------- 366 367 Returns an open ``File`` object that can be used to access the file's contents. 368 The ``mode`` represents all the same values as Python's own ``open()``, and 369 should be used to determine how the file can be accessed. See below for details 370 regarding how the returned ``File`` object should be behave for reading and 371 writing content. 372 373 ``_save(name, content)`` 374 ------------------------ 375 376 Stores the given content to the persistent storage backed by the class. The 377 ``name`` will already have gone through ``get_valid_name()`` and 378 ``get_available_name()``, and the ``content`` will be a ``File`` object itself. 379 This method has no return value. 380 381 Providing a ``File`` 382 -------------------- 383 384 Since the ``open()`` method returns a ``File`` object, it's expected that a 385 ``Storage`` subclass will provide a customized version that's designed to 386 interact with the underlying storage system. Many methods, such as ``read()``, 387 ``write()`` and ``close()``, should be overridden on this new ``File`` subclass, 388 so that it can transparently access the file's contents. -
docs/model-api.txt
228 228 ``FileField`` 229 229 ~~~~~~~~~~~~~ 230 230 231 A file-upload field. Has one **required** argument: 231 A file-upload field. Has two special arguments, of which the first is 232 **required**: 232 233 233 234 ====================== =================================================== 234 235 Argument Description 235 236 ====================== =================================================== 236 ``upload_to`` A local filesystem path that will be appended to 237 your ``MEDIA_ROOT`` setting to determine the 238 output of the ``get_<fieldname>_url()`` helper 239 function. 237 ``upload_to`` Required. A filesystem-style path that will be 238 prepended to the filename before being committed to 239 the final storage destination. 240 241 **New in Django development version** 242 243 This may also be a callable, such as a function, 244 which will be called to obtain the upload path, 245 including the filename. See below for details. 246 247 ``storage`` **New in Django development version** 248 249 Optional. A storage object, which handles the 250 storage and retrieval of your files. See `managing 251 files`_ for details on how to provide this object. 240 252 ====================== =================================================== 241 253 242 This path may contain `strftime formatting`_, which will be replaced by the 243 date/time of the file upload (so that uploaded files don't fill up the given 244 directory). 254 .. _managing files: ../files/ 245 255 256 The ``upload_to`` path may contain `strftime formatting`_, which will be 257 replaced by the date/time of the file upload (so that uploaded files don't fill 258 up the given directory). 259 260 **New in Django development version** 261 262 If a callable is provided for the ``upload_to`` argument, that callable must be 263 able to accept two arguments, and return a Unix-style path (with forward 264 slashes) to be passed along to the storage system. The two arguments that will 265 be passed are: 266 267 ====================== =================================================== 268 Argument Description 269 ====================== =================================================== 270 ``instance`` An instance of the model where the ``FileField`` is 271 defined. More specifically, this is the particular 272 instance where the current file is being attached. 273 274 **Note**: In most cases, this object will not have 275 been saved to the database yet, so if it uses the 276 default ``AutoField``, *it might not yet have a 277 value for its primary key field*. 278 279 ``filename`` The filename that was originally given to the file. 280 This may or may not be taken into account when 281 determining the final destination path. 282 ====================== =================================================== 283 246 284 The admin represents this field as an ``<input type="file">`` (a file-upload 247 285 widget). 248 286 249 Using a ``FileField`` or an ``ImageField`` (see below) in a model takes a few250 s teps:287 Using a ``FileField`` or an ``ImageField`` (see below) in a model without a 288 specified storage system takes a few steps: 251 289 252 290 1. In your settings file, you'll need to define ``MEDIA_ROOT`` as the 253 291 full path to a directory where you'd like Django to store uploaded -
docs/settings.txt
426 426 isn't manually specified. Used with ``DEFAULT_CHARSET`` to construct the 427 427 ``Content-Type`` header. 428 428 429 DEFAULT_FILE_STORAGE 430 -------------------- 431 432 Default: ``'django.core.filestorage.filesystem.FileSystemStorage'`` 433 434 Default file storage class to be used for any file-related operations that don't 435 specify a particular storage system. See the `file documentation`_ for details. 436 437 .. _file documentation: ../files/ 438 429 439 DEFAULT_FROM_EMAIL 430 440 ------------------ 431 441 -
docs/upload_handling.txt
155 155 ``UploadedFile`` objects 156 156 ======================== 157 157 158 All ``UploadedFile`` objects define the following methods/attributes: 158 In addition to those inherited from `File`_, all ``UploadedFile`` objects define 159 the following methods/attributes: 159 160 160 ``UploadedFile.read(self, num_bytes=None)``161 Returns a byte string of length ``num_bytes``, or the complete file if162 ``num_bytes`` is ``None``.163 164 ``UploadedFile.chunks(self, chunk_size=None)``165 A generator yielding small chunks from the file. If ``chunk_size`` isn't166 given, chunks will be 64 KB.167 168 ``UploadedFile.multiple_chunks(self, chunk_size=None)``169 Returns ``True`` if you can expect more than one chunk when calling170 ``UploadedFile.chunks(self, chunk_size)``.171 172 ``UploadedFile.size``173 The size, in bytes, of the uploaded file.174 175 ``UploadedFile.name``176 The name of the uploaded file as provided by the user.177 178 161 ``UploadedFile.content_type`` 179 162 The content-type header uploaded with the file (e.g. ``text/plain`` or 180 163 ``application/pdf``). Like any data supplied by the user, you shouldn't … … 186 169 For ``text/*`` content-types, the character set (i.e. ``utf8``) supplied 187 170 by the browser. Again, "trust but verify" is the best policy here. 188 171 189 ``UploadedFile.__iter__()``190 Iterates over the lines in the file.191 192 172 ``UploadedFile.temporary_file_path()`` 193 173 Only files uploaded onto disk will have this method; it returns the full 194 174 path to the temporary uploaded file. 195 175 176 .. _File: ../files/ 196 177 197 178 Upload Handlers 198 179 =============== -
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 def random_upload_to(self, filename): 25 # This returns a different result each time, 26 # to make sure it only gets called once. 27 import random 28 return '%s/%s' % (random.randint(100, 999), filename) 29 30 normal = models.FileField(storage=temp_storage, upload_to='tests') 31 custom = models.FileField(storage=temp_storage, upload_to=custom_upload_to) 32 random = models.FileField(storage=temp_storage, upload_to=random_upload_to) 33 default = models.FileField(storage=temp_storage, upload_to='tests', default='tests/default.txt') 34 35 __test__ = {'API_TESTS':""" 36 # An object without a file has limited functionality. 37 38 >>> obj1 = Storage() 39 >>> obj1.normal 40 <FieldFile: None> 41 >>> obj1.normal.size 42 Traceback (most recent call last): 43 ... 44 ValueError: The 'normal' attribute has no file associated with it. 45 46 # Saving a file enables full functionality. 47 48 >>> obj1.normal.save('django_test.txt', ContentFile('content')) 49 >>> obj1.normal 50 <FieldFile: tests/django_test.txt> 51 >>> obj1.normal.size 52 7 53 >>> obj1.normal.read() 54 'content' 55 56 # Files can be read in a little at a time, if necessary. 57 58 >>> obj1.normal.open() 59 >>> obj1.normal.read(3) 60 'con' 61 >>> obj1.normal.read() 62 'tent' 63 >>> '-'.join(obj1.normal.chunks(chunk_size=2)) 64 'co-nt-en-t' 65 66 # Save another file with the same name. 67 68 >>> obj2 = Storage() 69 >>> obj2.normal.save('django_test.txt', ContentFile('more content')) 70 >>> obj2.normal 71 <FieldFile: tests/django_test_.txt> 72 >>> obj2.normal.size 73 12 74 75 # Push the objects into the cache to make sure they pickle properly 76 77 >>> cache.set('obj1', obj1) 78 >>> cache.set('obj2', obj2) 79 >>> cache.get('obj2').normal 80 <FieldFile: tests/django_test_.txt> 81 82 # Deleting an object deletes the file it uses, if there are no other objects 83 # still using that file. 84 85 >>> obj2.delete() 86 >>> obj2.normal.save('django_test.txt', ContentFile('more content')) 87 >>> obj2.normal 88 <FieldFile: tests/django_test_.txt> 89 90 # Default values allow an object to access a single file. 91 92 >>> obj3 = Storage.objects.create() 93 >>> obj3.default 94 <FieldFile: tests/default.txt> 95 >>> obj3.default.read() 96 'default content' 97 98 # But it shouldn't be deleted, even if there are no more objects using it. 99 100 >>> obj3.delete() 101 >>> obj3 = Storage() 102 >>> obj3.default.read() 103 'default content' 104 105 # Verify the fix for #5655, making sure the directory is only determined once. 106 107 >>> obj4 = Storage() 108 >>> obj4.random.save('random_file', ContentFile('random content')) 109 >>> obj4.random 110 <FieldFile: .../random_file> 111 112 # Clean up the temporary files. 113 114 >>> obj1.normal.delete() 115 >>> obj2.normal.delete() 116 >>> obj3.default.delete() 117 >>> obj4.random.delete() 118 """} -
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 … … 73 76 # for PyPy, you need to check for the underlying modules 74 77 # If PIL is not available, this test is equivalent to TextFile above. 75 78 import Image, _imaging 76 image = models.ImageField( upload_to=tempfile.gettempdir())79 image = models.ImageField(storage=temp_storage, upload_to='tests') 77 80 except ImportError: 78 image = models.FileField( upload_to=tempfile.gettempdir())81 image = models.FileField(storage=temp_storage, upload_to='tests') 79 82 80 83 def __unicode__(self): 81 84 return self.description … … 786 789 787 790 # FileField ################################################################### 788 791 792 # File forms. 793 789 794 >>> class TextFileForm(ModelForm): 790 795 ... class Meta: 791 796 ... model = TextFile … … 808 813 <class 'django.core.files.uploadedfile.SimpleUploadedFile'> 809 814 >>> instance = f.save() 810 815 >>> instance.file 811 u'...test1.txt' 816 <FieldFile: tests/test1.txt> 812 817 813 >>> os.unlink(instance.get_file_filename())818 >>> instance.file.delete() 814 819 815 820 >>> f = TextFileForm(data={'description': u'Assistance'}, files={'file': SimpleUploadedFile('test1.txt', 'hello world')}) 816 821 >>> f.is_valid() … … 819 824 <class 'django.core.files.uploadedfile.SimpleUploadedFile'> 820 825 >>> instance = f.save() 821 826 >>> instance.file 822 u'...test1.txt' 827 <FieldFile: tests/test1.txt> 823 828 824 829 # Edit an instance that already has the file defined in the model. This will not 825 830 # save the file again, but leave it exactly as it is. … … 828 833 >>> f.is_valid() 829 834 True 830 835 >>> f.cleaned_data['file'] 831 u'...test1.txt' 836 <FieldFile: tests/test1.txt> 832 837 >>> instance = f.save() 833 838 >>> instance.file 834 u'...test1.txt' 839 <FieldFile: tests/test1.txt> 835 840 836 841 # Delete the current file since this is not done by Django. 837 >>> os.unlink(instance.get_file_filename())842 >>> instance.file.delete() 838 843 839 844 # Override the file by uploading a new one. 840 845 … … 843 848 True 844 849 >>> instance = f.save() 845 850 >>> instance.file 846 u'...test2.txt' 851 <FieldFile: tests/test2.txt> 847 852 848 853 # Delete the current file since this is not done by Django. 849 >>> os.unlink(instance.get_file_filename())854 >>> instance.file.delete() 850 855 851 856 >>> f = TextFileForm(data={'description': u'Assistance'}, files={'file': SimpleUploadedFile('test2.txt', 'hello world')}) 852 857 >>> f.is_valid() 853 858 True 854 859 >>> instance = f.save() 855 860 >>> instance.file 856 u'...test2.txt' 861 <FieldFile: tests/test2.txt> 857 862 858 863 # Delete the current file since this is not done by Django. 859 >>> os.unlink(instance.get_file_filename())864 >>> instance.file.delete() 860 865 861 866 >>> instance.delete() 862 867 … … 868 873 True 869 874 >>> instance = f.save() 870 875 >>> instance.file 871 '' 876 <FieldFile: None> 872 877 873 878 >>> f = TextFileForm(data={'description': u'Assistance'}, files={'file': SimpleUploadedFile('test3.txt', 'hello world')}, instance=instance) 874 879 >>> f.is_valid() 875 880 True 876 881 >>> instance = f.save() 877 882 >>> instance.file 878 u'...test3.txt' 883 <FieldFile: tests/test3.txt> 879 884 880 885 # Delete the current file since this is not done by Django. 881 >>> os.unlink(instance.get_file_filename())886 >>> instance.file.delete() 882 887 >>> instance.delete() 883 888 884 889 >>> f = TextFileForm(data={'description': u'Assistance'}, files={'file': SimpleUploadedFile('test3.txt', 'hello world')}) … … 886 891 True 887 892 >>> instance = f.save() 888 893 >>> instance.file 889 u'...test3.txt' 894 <FieldFile: tests/test3.txt> 890 895 891 896 # Delete the current file since this is not done by Django. 892 >>> os.unlink(instance.get_file_filename())897 >>> instance.file.delete() 893 898 >>> instance.delete() 894 899 895 900 # ImageField ################################################################### … … 911 916 <class 'django.core.files.uploadedfile.SimpleUploadedFile'> 912 917 >>> instance = f.save() 913 918 >>> instance.image 914 u'...test.png' 919 <ImageFieldFile: tests/test.png> 915 920 916 921 # Delete the current file since this is not done by Django. 917 >>> os.unlink(instance.get_image_filename())922 >>> instance.image.delete() 918 923 919 924 >>> f = ImageFileForm(data={'description': u'An image'}, files={'image': SimpleUploadedFile('test.png', image_data)}) 920 925 >>> f.is_valid() … … 923 928 <class 'django.core.files.uploadedfile.SimpleUploadedFile'> 924 929 >>> instance = f.save() 925 930 >>> instance.image 926 u'...test.png' 931 <ImageFieldFile: tests/test.png> 927 932 928 933 # Edit an instance that already has the image defined in the model. This will not 929 934 # save the image again, but leave it exactly as it is. … … 932 937 >>> f.is_valid() 933 938 True 934 939 >>> f.cleaned_data['image'] 935 u'...test.png' 940 <ImageFieldFile: tests/test.png> 936 941 >>> instance = f.save() 937 942 >>> instance.image 938 u'...test.png' 943 <ImageFieldFile: tests/test.png> 939 944 940 945 # Delete the current image since this is not done by Django. 941 946 942 >>> os.unlink(instance.get_image_filename())947 >>> instance.image.delete() 943 948 944 949 # Override the file by uploading a new one. 945 950 … … 948 953 True 949 954 >>> instance = f.save() 950 955 >>> instance.image 951 u'...test2.png' 956 <ImageFieldFile: tests/test2.png> 952 957 953 958 # Delete the current file since this is not done by Django. 954 >>> os.unlink(instance.get_image_filename())959 >>> instance.image.delete() 955 960 >>> instance.delete() 956 961 957 962 >>> f = ImageFileForm(data={'description': u'Changed it'}, files={'image': SimpleUploadedFile('test2.png', image_data)}) … … 959 964 True 960 965 >>> instance = f.save() 961 966 >>> instance.image 962 u'...test2.png' 967 <ImageFieldFile: tests/test2.png> 963 968 964 969 # Delete the current file since this is not done by Django. 965 >>> os.unlink(instance.get_image_filename())970 >>> instance.image.delete() 966 971 >>> instance.delete() 967 972 968 973 # Test the non-required ImageField … … 973 978 True 974 979 >>> instance = f.save() 975 980 >>> instance.image 976 '' 981 <ImageFieldFile: None> 977 982 978 983 >>> f = ImageFileForm(data={'description': u'And a final one'}, files={'image': SimpleUploadedFile('test3.png', image_data)}, instance=instance) 979 984 >>> f.is_valid() 980 985 True 981 986 >>> instance = f.save() 982 987 >>> instance.image 983 u'...test3.png' 988 <ImageFieldFile: tests/test3.png> 984 989 985 990 # Delete the current file since this is not done by Django. 986 >>> os.unlink(instance.get_image_filename())991 >>> instance.image.delete() 987 992 >>> instance.delete() 988 993 989 994 >>> f = ImageFileForm(data={'description': u'And a final one'}, files={'image': SimpleUploadedFile('test3.png', image_data)}) … … 991 996 True 992 997 >>> instance = f.save() 993 998 >>> instance.image 994 u'...test3.png' 999 <ImageFieldFile: tests/test3.png> 995 1000 >>> instance.delete() 996 1001 997 1002 # 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, open 6 >>> from django.core.files.base import ContentFile 7 8 >>> temp_storage = FileSystemStorage(location=tempfile.gettempdir()) 9 10 # Standard file access options are available, and work as expected. 11 12 >>> temp_storage.exists('storage_test') 13 False 14 >>> file = temp_storage.open('storage_test', 'w') 15 >>> file.write('storage contents') 16 >>> file.close() 17 18 >>> temp_storage.exists('storage_test') 19 True 20 >>> file = temp_storage.open('storage_test', 'r') 21 >>> file.read() 22 'storage contents' 23 >>> file.close() 24 25 >>> temp_storage.delete('storage_test') 26 >>> temp_storage.exists('storage_test') 27 False 28 29 # Files can only be accessed if they're below the specified location. 30 31 >>> temp_storage.exists('..') 32 Traceback (most recent call last): 33 ... 34 SuspiciousOperation: Attempted access to '..' denied. 35 >>> temp_storage.open('/etc/passwd') 36 Traceback (most recent call last): 37 ... 38 SuspiciousOperation: Attempted access to '/etc/passwd' denied. 39 40 # RemoteFile allows files to be committed by way of a user-defined function. 41 42 >>> from django.core.files.remote import RemoteFile 43 >>> def write_file(contents): 44 ... print 'Writing %s' % contents 45 46 # Opening for read access doesn't commit back to the server 47 48 >>> file = RemoteFile('', 'r', write_file) 49 >>> file.close() 50 51 # The same goes for opening for write access, but not actually writing 52 53 >>> file = RemoteFile('', 'w', write_file) 54 >>> file.close() 55 56 # But once it's written to, it gets committed on close 57 58 >>> file = RemoteFile('', 'w', write_file) 59 >>> file.write('remote contents') # Content isn't committed yet 60 >>> file.close() # Content gets committed to the storage system 61 Writing remote contents 62 63 # Custom storage systems can be created to customize behavior 64 65 >>> class CustomStorage(FileSystemStorage): 66 ... def get_available_name(self, name): 67 ... # Append numbers to duplicate files rather than underscores, like Trac 68 ... 69 ... parts = name.split('.') 70 ... basename, ext = parts[0], parts[1:] 71 ... number = 2 72 ... 73 ... while self.exists(name): 74 ... name = '.'.join([basename, str(number)] + ext) 75 ... number += 1 76 ... 77 ... return name 78 >>> custom_storage = CustomStorage(tempfile.gettempdir()) 79 80 >>> first = custom_storage.save('custom_storage', ContentFile('custom contents')) 81 >>> first 82 u'custom_storage' 83 >>> second = custom_storage.save('custom_storage', ContentFile('more contents')) 84 >>> second 85 u'custom_storage.2' 86 87 >>> custom_storage.delete(first) 88 >>> custom_storage.delete(second) 89 """