Ticket #5361: 5361-r8222.diff
File 5361-r8222.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/contrib/admin/widgets.py
85 85 def render(self, name, value, attrs=None): 86 86 output = [] 87 87 if value: 88 output.append('%s <a target="_blank" href="%s %s">%s</a> <br />%s ' % \89 (_('Currently:'), settings.MEDIA_URL, value, value, _('Change:')))88 output.append('%s <a target="_blank" href="%s">%s</a> <br />%s ' % \ 89 (_('Currently:'), value.url, value, _('Change:'))) 90 90 output.append(super(AdminFileWidget, self).render(name, value, attrs)) 91 91 return mark_safe(u''.join(output)) 92 92 -
django/core/files/__init__.py
1 from django.core.files.base import File -
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=None): 118 if not self.closed: 119 self.seek(0) 120 elif os.path.exists(self.file.name): 121 self.file = open(self.file.name, mode or 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/storage.py
1 import os 2 import urlparse 3 4 from django.conf import settings 5 from django.core.exceptions import ImproperlyConfigured, SuspiciousOperation 6 from django.utils.encoding import force_unicode, smart_str 7 from django.utils.text import force_unicode, get_valid_filename 8 from django.utils._os import safe_join 9 from django.core.files import locks, File 10 11 __all__ = ('Storage', 'FileSystemStorage', 'DefaultStorage', 'default_storage') 12 13 class Storage(object): 14 """ 15 A base storage class, providing some default behaviors that all other 16 storage systems can inherit or override, as necessary. 17 """ 18 19 # The following methods represent a public interface to private methods. 20 # These shouldn't be overridden by subclasses unless absolutely necessary. 21 22 def open(self, name, mode='rb', mixin=None): 23 """ 24 Retrieves the specified file from storage, using the optional mixin 25 class to customize what features are available on the File returned. 26 """ 27 file = self._open(name, mode) 28 if mixin: 29 # Add the mixin as a parent class of the File returned from storage. 30 file.__class__ = type(mixin.__name__, (mixin, file.__class__), {}) 31 return file 32 33 def save(self, name, content): 34 """ 35 Saves new content to the file specified by name. The content should be a 36 proper File object, ready to be read from the beginning. 37 """ 38 # Check for old-style usage. Warn here first since there are multiple 39 # locations where we need to support both new and old usage. 40 if isinstance(content, basestring): 41 import warnings 42 warnings.warn( 43 message = "Representing files as strings is deprecated." \ 44 "Use django.core.files.base.ContentFile instead.", 45 category = DeprecationWarning, 46 stacklevel = 2 47 ) 48 from django.core.files.base import ContentFile 49 content = ContentFile(content) 50 51 # Get the proper name for the file, as it will actually be saved. 52 if name is None: 53 name = content.name 54 name = self.get_available_name(name) 55 56 self._save(name, content) 57 58 # Store filenames with forward slashes, even on Windows 59 return force_unicode(name.replace('\\', '/')) 60 61 # These methods are part of the public API, with default implementations. 62 63 def get_valid_name(self, name): 64 """ 65 Returns a filename, based on the provided filename, that's suitable for 66 use in the target storage system. 67 """ 68 return get_valid_filename(name) 69 70 def get_available_name(self, name): 71 """ 72 Returns a filename that's free on the target storage system, and 73 available for new content to be written to. 74 """ 75 # If the filename already exists, keep adding an underscore to the name 76 # of the file until the filename doesn't exist. 77 while self.exists(name): 78 try: 79 dot_index = name.rindex('.') 80 except ValueError: # filename has no dot 81 name += '_' 82 else: 83 name = name[:dot_index] + '_' + name[dot_index:] 84 return name 85 86 def path(self, name): 87 """ 88 Returns a local filesystem path where the file can be retrieved using 89 Python's built-in open() function. Storage systems that can't be 90 accessed using open() should *not* implement this method. 91 """ 92 raise NotImplementedError("This backend doesn't support absolute paths.") 93 94 # The following methods form the public API for storage systems, but with 95 # no default implementations. Subclasses must implement *all* of these. 96 97 def delete(self, name): 98 """ 99 Deletes the specified file from the storage system. 100 """ 101 raise NotImplementedError() 102 103 def exists(self, name): 104 """ 105 Returns True if a file referened by the given name already exists in the 106 storage system, or False if the name is available for a new file. 107 """ 108 raise NotImplementedError() 109 110 def listdir(self, path): 111 """ 112 Lists the contents of the specified path, returning a 2-tuple of lists; 113 the first item being directories, the second item being files. 114 """ 115 raise NotImplementedError() 116 117 def size(self, name): 118 """ 119 Returns the total size, in bytes, of the file specified by name. 120 """ 121 raise NotImplementedError() 122 123 def url(self, name): 124 """ 125 Returns an absolute URL where the file's contents can be accessed 126 directly by a web browser. 127 """ 128 raise NotImplementedError() 129 130 class FileSystemStorage(Storage): 131 """ 132 Standard filesystem storage 133 """ 134 135 def __init__(self, location=settings.MEDIA_ROOT, base_url=settings.MEDIA_URL): 136 self.location = os.path.abspath(location) 137 self.base_url = base_url 138 139 def _open(self, name, mode='rb'): 140 return File(open(self.path(name), mode)) 141 142 def _save(self, name, content): 143 full_path = self.path(name) 144 145 directory = os.path.dirname(full_path) 146 if not os.path.exists(directory): 147 os.makedirs(directory) 148 elif not os.path.isdir(directory): 149 raise IOError("%s exists and is not a directory." % directory) 150 151 if hasattr(content, 'temporary_file_path'): 152 # This file has a file path that we can move. 153 file_move_safe(content.temporary_file_path(), full_path) 154 content.close() 155 else: 156 # This is a normal uploadedfile that we can stream. 157 fp = open(full_path, 'wb') 158 locks.lock(fp, locks.LOCK_EX) 159 for chunk in content.chunks(): 160 fp.write(chunk) 161 locks.unlock(fp) 162 fp.close() 163 164 def delete(self, name): 165 name = self.path(name) 166 # If the file exists, delete it from the filesystem. 167 if os.path.exists(name): 168 os.remove(name) 169 170 def exists(self, name): 171 return os.path.exists(self.path(name)) 172 173 def listdir(self, path): 174 path = self.path(path) 175 directories, files = [], [] 176 for entry in os.listdir(path): 177 if os.path.isdir(os.path.join(path, entry)): 178 directories.append(entry) 179 else: 180 files.append(entry) 181 return directories, files 182 183 def path(self, name): 184 try: 185 path = safe_join(self.location, name) 186 except ValueError: 187 raise SuspiciousOperation("Attempted access to '%s' denied." % name) 188 return os.path.normpath(path) 189 190 def size(self, name): 191 return os.path.getsize(self.path(name)) 192 193 def url(self, name): 194 if self.base_url is None: 195 raise ValueError("This file is not accessible via a URL.") 196 return urlparse.urljoin(self.base_url, name).replace('\\', '/') 197 198 def get_storage_class(import_path): 199 try: 200 dot = import_path.rindex('.') 201 except ValueError: 202 raise ImproperlyConfigured("%s isn't a storage module." % import_path) 203 module, classname = import_path[:dot], import_path[dot+1:] 204 try: 205 mod = __import__(module, {}, {}, ['']) 206 except ImportError, e: 207 raise ImproperlyConfigured('Error importing storage module %s: "%s"' % (module, e)) 208 try: 209 return getattr(mod, classname) 210 except AttributeError: 211 raise ImproperlyConfigured('Storage module "%s" does not define a "%s" class.' % (module, classname)) 212 213 DefaultStorage = get_storage_class(settings.DEFAULT_FILE_STORAGE) 214 default_storage = DefaultStorage() -
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 … … 465 466 return getattr(self, cachename) 466 467 467 468 def _get_FIELD_filename(self, field): 468 if getattr(self, field.attname): # Value is not blank. 469 return os.path.normpath(os.path.join(settings.MEDIA_ROOT, getattr(self, field.attname))) 470 return '' 469 warn("instance.get_%s_filename() is deprecated. Use instance.%s.path instead." % \ 470 (field.attname, field.attname), DeprecationWarning, stacklevel=3) 471 try: 472 return getattr(self, field.attname).path 473 except ValueError: 474 return '' 471 475 472 476 def _get_FIELD_url(self, field): 473 if getattr(self, field.attname): # Value is not blank. 474 import urlparse 475 return urlparse.urljoin(settings.MEDIA_URL, getattr(self, field.attname)).replace('\\', '/') 476 return '' 477 warn("instance.get_%s_url() is deprecated. Use instance.%s.url instead." % \ 478 (field.attname, field.attname), DeprecationWarning, stacklevel=3) 479 try: 480 return getattr(self, field.attname).url 481 except ValueError: 482 return '' 477 483 478 484 def _get_FIELD_size(self, field): 479 return os.path.getsize(self._get_FIELD_filename(field)) 485 warn("instance.get_%s_size() is deprecated. Use instance.%s.size instead." % \ 486 (field.attname, field.attname), DeprecationWarning, stacklevel=3) 487 return getattr(self, field.attname).size 480 488 481 def _save_FIELD_file(self, field, filename, raw_field, save=True): 482 # Create the upload directory if it doesn't already exist 483 directory = os.path.join(settings.MEDIA_ROOT, field.get_directory_name()) 484 if not os.path.exists(directory): 485 os.makedirs(directory) 486 elif not os.path.isdir(directory): 487 raise IOError('%s exists and is not a directory' % directory) 489 def _save_FIELD_file(self, field, filename, content, save=True): 490 warn("instance.save_%s_file() is deprecated. Use instance.%s.save() instead." % \ 491 (field.attname, field.attname), DeprecationWarning, stacklevel=3) 492 return getattr(self, field.attname).save(filename, content, save) 488 493 489 # Check for old-style usage (files-as-dictionaries). Warn here first490 # since there are multiple locations where we need to support both new491 # and old usage.492 if isinstance(raw_field, dict):493 import warnings494 warnings.warn(495 message = "Representing uploaded files as dictionaries is deprecated. Use django.core.files.uploadedfile.SimpleUploadedFile instead.",496 category = DeprecationWarning,497 stacklevel = 2498 )499 from django.core.files.uploadedfile import SimpleUploadedFile500 raw_field = SimpleUploadedFile.from_dict(raw_field)501 502 elif isinstance(raw_field, basestring):503 import warnings504 warnings.warn(505 message = "Representing uploaded files as strings is deprecated. Use django.core.files.uploadedfile.SimpleUploadedFile instead.",506 category = DeprecationWarning,507 stacklevel = 2508 )509 from django.core.files.uploadedfile import SimpleUploadedFile510 raw_field = SimpleUploadedFile(filename, raw_field)511 512 if filename is None:513 filename = raw_field.file_name514 515 filename = field.get_filename(filename)516 517 # If the filename already exists, keep adding an underscore to the name518 # of the file until the filename doesn't exist.519 while os.path.exists(os.path.join(settings.MEDIA_ROOT, filename)):520 try:521 dot_index = filename.rindex('.')522 except ValueError: # filename has no dot.523 filename += '_'524 else:525 filename = filename[:dot_index] + '_' + filename[dot_index:]526 527 # Save the file name on the object and write the file to disk.528 setattr(self, field.attname, filename)529 full_filename = self._get_FIELD_filename(field)530 if hasattr(raw_field, 'temporary_file_path'):531 # This file has a file path that we can move.532 file_move_safe(raw_field.temporary_file_path(), full_filename)533 raw_field.close()534 else:535 # This is a normal uploadedfile that we can stream.536 fp = open(full_filename, 'wb')537 locks.lock(fp, locks.LOCK_EX)538 for chunk in raw_field.chunks():539 fp.write(chunk)540 locks.unlock(fp)541 fp.close()542 543 # Save the width and/or height, if applicable.544 if isinstance(field, ImageField) and \545 (field.width_field or field.height_field):546 from django.utils.images import get_image_dimensions547 width, height = get_image_dimensions(full_filename)548 if field.width_field:549 setattr(self, field.width_field, width)550 if field.height_field:551 setattr(self, field.height_field, height)552 553 # Save the object because it has changed, unless save is False.554 if save:555 self.save()556 557 494 _save_FIELD_file.alters_data = True 558 495 559 496 def _get_FIELD_width(self, field): 560 return self._get_image_dimensions(field)[0] 497 warn("instance.get_%s_width() is deprecated. Use instance.%s.width instead." % \ 498 (field.attname, field.attname), DeprecationWarning, stacklevel=3) 499 return getattr(self, field.attname).width() 561 500 562 501 def _get_FIELD_height(self, field): 563 return self._get_image_dimensions(field)[1] 502 warn("instance.get_%s_height() is deprecated. Use instance.%s.height instead." % \ 503 (field.attname, field.attname), DeprecationWarning, stacklevel=3) 504 return getattr(self, field.attname).height() 564 505 565 def _get_image_dimensions(self, field):566 cachename = "__%s_dimensions_cache" % field.name567 if not hasattr(self, cachename):568 from django.utils.images import get_image_dimensions569 filename = self._get_FIELD_filename(field)570 setattr(self, cachename, get_image_dimensions(filename))571 return getattr(self, cachename)572 506 573 574 507 ############################################ 575 508 # HELPER FUNCTIONS (CURRIED MODEL METHODS) # 576 509 ############################################ -
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 … … 758 757 defaults.update(kwargs) 759 758 return super(EmailField, self).formfield(**defaults) 760 759 761 class FileField(Field):762 def __init__(self, verbose_name=None, name=None, upload_to='', **kwargs):763 self.upload_to = upload_to764 kwargs['max_length'] = kwargs.get('max_length', 100)765 Field.__init__(self, verbose_name, name, **kwargs)766 767 def get_internal_type(self):768 return "FileField"769 770 def get_db_prep_value(self, value):771 "Returns field's value prepared for saving into a database."772 # Need to convert UploadedFile objects provided via a form to unicode for database insertion773 if hasattr(value, 'name'):774 return value.name775 elif value is None:776 return None777 else:778 return unicode(value)779 780 def get_manipulator_fields(self, opts, manipulator, change, name_prefix='', rel=False, follow=True):781 field_list = Field.get_manipulator_fields(self, opts, manipulator, change, name_prefix, rel, follow)782 if not self.blank:783 if rel:784 # This validator makes sure FileFields work in a related context.785 class RequiredFileField(object):786 def __init__(self, other_field_names, other_file_field_name):787 self.other_field_names = other_field_names788 self.other_file_field_name = other_file_field_name789 self.always_test = True790 def __call__(self, field_data, all_data):791 if not all_data.get(self.other_file_field_name, False):792 c = validators.RequiredIfOtherFieldsGiven(self.other_field_names, ugettext_lazy("This field is required."))793 c(field_data, all_data)794 # First, get the core fields, if any.795 core_field_names = []796 for f in opts.fields:797 if f.core and f != self:798 core_field_names.extend(f.get_manipulator_field_names(name_prefix))799 # Now, if there are any, add the validator to this FormField.800 if core_field_names:801 field_list[0].validator_list.append(RequiredFileField(core_field_names, field_list[1].field_name))802 else:803 v = validators.RequiredIfOtherFieldNotGiven(field_list[1].field_name, ugettext_lazy("This field is required."))804 v.always_test = True805 field_list[0].validator_list.append(v)806 field_list[0].is_required = field_list[1].is_required = False807 808 # If the raw path is passed in, validate it's under the MEDIA_ROOT.809 def isWithinMediaRoot(field_data, all_data):810 f = os.path.abspath(os.path.join(settings.MEDIA_ROOT, field_data))811 if not f.startswith(os.path.abspath(os.path.normpath(settings.MEDIA_ROOT))):812 raise validators.ValidationError, _("Enter a valid filename.")813 field_list[1].validator_list.append(isWithinMediaRoot)814 return field_list815 816 def contribute_to_class(self, cls, name):817 super(FileField, self).contribute_to_class(cls, name)818 setattr(cls, 'get_%s_filename' % self.name, curry(cls._get_FIELD_filename, field=self))819 setattr(cls, 'get_%s_url' % self.name, curry(cls._get_FIELD_url, field=self))820 setattr(cls, 'get_%s_size' % self.name, curry(cls._get_FIELD_size, field=self))821 setattr(cls, 'save_%s_file' % self.name, lambda instance, filename, raw_field, save=True: instance._save_FIELD_file(self, filename, raw_field, save))822 dispatcher.connect(self.delete_file, signal=signals.post_delete, sender=cls)823 824 def delete_file(self, instance):825 if getattr(instance, self.attname):826 file_name = getattr(instance, 'get_%s_filename' % self.name)()827 # If the file exists and no other object of this type references it,828 # delete it from the filesystem.829 if os.path.exists(file_name) and \830 not instance.__class__._default_manager.filter(**{'%s__exact' % self.name: getattr(instance, self.attname)}):831 os.remove(file_name)832 833 def get_manipulator_field_objs(self):834 return [oldforms.FileUploadField, oldforms.HiddenField]835 836 def get_manipulator_field_names(self, name_prefix):837 return [name_prefix + self.name + '_file', name_prefix + self.name]838 839 def save_file(self, new_data, new_object, original_object, change, rel, save=True):840 upload_field_name = self.get_manipulator_field_names('')[0]841 if new_data.get(upload_field_name, False):842 if rel:843 file = new_data[upload_field_name][0]844 else:845 file = new_data[upload_field_name]846 847 if not file:848 return849 850 # Backwards-compatible support for files-as-dictionaries.851 # We don't need to raise a warning because Model._save_FIELD_file will852 # do so for us.853 try:854 file_name = file.name855 except AttributeError:856 file_name = file['filename']857 858 func = getattr(new_object, 'save_%s_file' % self.name)859 func(file_name, file, save)860 861 def get_directory_name(self):862 return os.path.normpath(force_unicode(datetime.datetime.now().strftime(smart_str(self.upload_to))))863 864 def get_filename(self, filename):865 from django.utils.text import get_valid_filename866 f = os.path.join(self.get_directory_name(), get_valid_filename(os.path.basename(filename)))867 return os.path.normpath(f)868 869 def save_form_data(self, instance, data):870 from django.core.files.uploadedfile import UploadedFile871 if data and isinstance(data, UploadedFile):872 getattr(instance, "save_%s_file" % self.name)(data.name, data, save=False)873 874 def formfield(self, **kwargs):875 defaults = {'form_class': forms.FileField}876 # If a file has been provided previously, then the form doesn't require877 # that a new file is provided this time.878 # The code to mark the form field as not required is used by879 # form_for_instance, but can probably be removed once form_for_instance880 # is gone. ModelForm uses a different method to check for an existing file.881 if 'initial' in kwargs:882 defaults['required'] = False883 defaults.update(kwargs)884 return super(FileField, self).formfield(**defaults)885 886 760 class FilePathField(Field): 887 761 def __init__(self, verbose_name=None, name=None, path='', match=None, recursive=False, **kwargs): 888 762 self.path, self.match, self.recursive = path, match, recursive … … 924 798 defaults.update(kwargs) 925 799 return super(FloatField, self).formfield(**defaults) 926 800 927 class ImageField(FileField):928 def __init__(self, verbose_name=None, name=None, width_field=None, height_field=None, **kwargs):929 self.width_field, self.height_field = width_field, height_field930 FileField.__init__(self, verbose_name, name, **kwargs)931 932 def get_manipulator_field_objs(self):933 return [oldforms.ImageUploadField, oldforms.HiddenField]934 935 def contribute_to_class(self, cls, name):936 super(ImageField, self).contribute_to_class(cls, name)937 # Add get_BLAH_width and get_BLAH_height methods, but only if the938 # image field doesn't have width and height cache fields.939 if not self.width_field:940 setattr(cls, 'get_%s_width' % self.name, curry(cls._get_FIELD_width, field=self))941 if not self.height_field:942 setattr(cls, 'get_%s_height' % self.name, curry(cls._get_FIELD_height, field=self))943 944 def save_file(self, new_data, new_object, original_object, change, rel, save=True):945 FileField.save_file(self, new_data, new_object, original_object, change, rel, save)946 # If the image has height and/or width field(s) and they haven't947 # changed, set the width and/or height field(s) back to their original948 # values.949 if change and (self.width_field or self.height_field) and save:950 if self.width_field:951 setattr(new_object, self.width_field, getattr(original_object, self.width_field))952 if self.height_field:953 setattr(new_object, self.height_field, getattr(original_object, self.height_field))954 new_object.save()955 956 def formfield(self, **kwargs):957 defaults = {'form_class': forms.ImageField}958 defaults.update(kwargs)959 return super(ImageField, self).formfield(**defaults)960 961 801 class IntegerField(Field): 962 802 empty_strings_allowed = False 963 803 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) 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 While there are several `File` subclasses that get created automatically, for 27 things like file uploading, the simplest way to get access to a ``File`` is to 28 just instantiate one using a true ``file`` from Python's own ``open()``:: 29 30 >>> from django.core.files import File 31 32 >>> writable = File(open('/tmp/hello_world', 'w')) 33 >>> writable.name, writable.mode 34 ('/tmp/hello_world', 'w') 35 >>> writable.write('Hello, world!') 36 >>> writable.close() 37 38 >>> readable = File(open('/tmp/hello_world')) 39 >>> readable.size 40 13 41 >>> readable.close() 42 43 ``path`` 44 -------- 45 46 Returns the absolute path to the file's location on a local filesystem. For 47 storage systems which do not store files locally, this will return ``None``. 48 49 ``url`` 50 ------- 51 52 Provides a URL where the content of the file can be retrieved. Therefore, 53 returned from this method is suitable for use as the destination of a link to 54 the file. 55 56 ``size`` 57 -------- 58 59 Returns the size of the file, as an integer. 60 61 ``open(mode=None)`` 62 ------------------- 63 64 Reopens the file, resetting the internal pointer back to the beginning. The 65 ``mode`` argument allows the same values as Python's standard ``open()``. If 66 provided, ``mode`` will override whatever mode the file was opened with, while 67 omitting it will reopen the file using the same mode used before it was closed. 68 69 ``read(num_bytes=None)`` 70 ------------------------ 71 72 Retrieves some content from the file, returning it as a string. The optional 73 ``size`` is the number of bytes to read; if not specified, the file will be read 74 through to the end. 75 76 ``__iter__()`` 77 -------------- 78 79 Iterates over the lines in the file, preserving newline characters on each line. 80 This allows the file to be used in simple loops, using ``for line in file``. 81 82 ``chunks(chunk_size=None)`` 83 --------------------------- 84 85 Yields the contents of the file in smaller chunks, that can be looped over to 86 access the file without loading it all into memory at once. If ``chunk_size`` 87 isn't provided, it defaults to 64 KB. 88 89 ``multiple_chunks(chunk_size=None)`` 90 ------------------------------------ 91 92 Returns ``True`` if the file is large enough to require multiple chunks to 93 access all of its content, or ``False`` if it can all be read in one pass. The 94 optional ``chunk_size`` works the same as in ``chunks()`` above. 95 96 ``write(content)`` 97 ------------------ 98 99 Writes the specified content string to the file. Depending on the storage system 100 behind the scenes, this content might not be fully committed until ``close()`` 101 is called on the file. 102 103 ``close()`` 104 ----------- 105 106 Closes the file, so it can't be read from or written to anymore. If there's 107 still any content that hasn't been written to the file itself, this will commit 108 that as well. 109 110 ``ImageFile`` 111 ============= 112 113 Anywhere Django can open a new file, it also accepts a mixin class to support 114 more specific file types. For images, there's a more specific ``ImageFile``, 115 available from ``django.core.files.images``. 116 117 ``width and height`` 118 -------------------- 119 120 When using an ``ImageField``, these two attributes will be available, providing 121 easy access to the dimensions of the image. 122 123 Using files in models 124 ===================== 125 126 When accessing a ``FileField`` attached to a model, a special object provides 127 access to the file and information about it. 128 129 Example 130 ------- 131 132 Consider the following model, using an ``ImageField`` to store a product photo:: 133 134 class Product(models.Model): 135 name = models.CharField(maxlength=255) 136 price = models.DecimalField(max_digits=5, decimal_places=2) 137 photo = models.ImageField(upload_to='product_photos') 138 139 Your views can then use the ``photo`` attribute with the functions described 140 above, as follows:: 141 142 >>> car = Product.object.get(name="'57 Chevy") 143 >>> car.photo 144 <ImageFieldFile: 123.jpg> 145 >>> car.photo.url 146 '/products/photo/123.jpg' 147 >>> car.photo.width, car.photo.height 148 (800, 600) 149 150 ``save(name, content, save=True)`` 151 ---------------------------------- 152 153 Saves a new file with the filename and contents provided. This will not replace 154 the existing file, but will create a new file and update the object to point to 155 it. The optional ``save`` argument dictates whether the model instance will be 156 saved to the database immediately. 157 158 ``delete(save=True)`` 159 --------------------- 160 161 Removes the file from the model instance and deletes it from the underlying 162 storage system. The optional ``save`` argument indicates whether the model 163 instance will saved to the database immediately. 164 165 Using a storage system with FileField 166 ===================================== 167 168 When using a storage system, supply whatever options are appropriate for 169 that system when creating a new object. Then pass that object as the ``storage`` 170 argument to a ``FileField``. Details on the requirements for the included 171 storage system can be found below. 172 173 If using the default storage system, it is not necessary to create a storage 174 object explicitly. In this case, the ``FileField`` will use the one referenced 175 by the `DEFAULT_FILE_STORAGE setting`_. 176 177 See the `FileField documentation`_ for more information on using the field. 178 179 .. _DEFAULT_FILE_STORAGE setting: ../settings/#default-file-storage 180 .. _FileField documentation: ../model-api/#filefield 181 182 For example, the following code will explicitly use the ``FileSystemStorage``:: 183 184 from django.db import models 185 from django.core.files.storage import FileSystemStorage 186 187 fs = FileSystemStorage(location='product_photos') 188 189 class Product(models.Model): 190 name = models.CharField(maxlength=255) 191 price = models.DecimalField(max_digits=5, decimal_places=2) 192 photo = models.ImageField(storage=fs) 193 194 Using a storage system on its own 195 ================================= 196 197 Storage systems may also be used directly, without being attached to a model. 198 Simply use the following API on any instantiated storage system to access files 199 without having to worry about the underlying mechanism. In addition to explicit 200 storage mechanisms, the file storage module, ``django.core.files.storage``, 201 exports a ``default_storage`` object that's automatically created from the 202 ``DEFAULT_FILE_STORAGE`` setting:: 203 204 >>> from django.core.files.storage import default_storage 205 206 With a functional storage system on hand, managing files is quite simple, with a 207 few basic methods to handle the most common operations:: 208 209 >>> path = storage.save('/path/to/file', 'new content') 210 >>> path 211 u'/path/to/file' 212 >>> storage.filesize(path) 213 11 214 >>> storage.open(path).read() 215 'new content' 216 >>> storage.delete(path) 217 >>> storage.exists(path) 218 False 219 220 ``exists(name)`` 221 ---------------- 222 223 Returns ``True`` or ``False, indicating whether there is already a file present 224 at the location referenced by``name``. 225 226 ``path(name)`` 227 -------------- 228 229 Returns the local filesystem path where the file can be opened using Python's 230 standard ``open()``. For storage systems that aren't accessible from the local 231 filesystem, this will raise ``NotImplementedError`` instead. 232 233 ``size(name)`` 234 -------------- 235 236 Returns the total size, in bytes, of the file referenced by ``name``. 237 238 ``url(name)`` 239 ------------- 240 241 Returns the URL where the contents of the file referenced by ``name`` can be 242 accessed. 243 244 ``open(name, mode='rb', mixin=None)`` 245 ------------------------------------- 246 247 Returns an open file, or file-like, object to provide access to the contents of 248 the file referenced by ``name``. The ``mode`` argument allows the same values as 249 Python's standard ``open()`` function. The ``mixin`` is an optional class that, 250 if provided, will be applied to the ``File`` object returned from this method. 251 252 ``save(name, content)`` 253 ----------------------- 254 255 Saves a new file using the storage system, preferably with the name specified. 256 If there already exists a file at the location referenced by ``name``, this may 257 modify the filename as necessary to locate one that is available. Once the file 258 is saved, this method will return the filename where the file was actually 259 stored. 260 261 ``delete(name)`` 262 ---------------- 263 264 Deletes the file referenced by ``name``. If the file does not already exist, 265 this method will simply return without raising an exception. 266 267 Available storage systems 268 ========================= 269 270 Only one storage system is supplied in the official Django distribution, but 271 more may be available elsewhere. If you'd like to use a different storage system 272 than the one listed below, see the documentation included with it. 273 274 ``django.core.files.storage.FileSystemStorage`` 275 ----------------------------------------------- 276 277 This simply stores files on the system's standard filesystem. 278 279 ====================== =================================================== 280 Argument Description 281 ====================== =================================================== 282 ``location`` Optional. Absolute path to the directory that will 283 hold the files. If omitted, it will be set to the 284 value of your ``MEDIA_ROOT`` setting. 285 ``base_url`` Optional. URL that serves the files stored at this 286 location. If omitted, it will default to the value 287 of your ``MEDIA_URL`` setting. 288 ====================== =================================================== 289 290 Writing a storage system 291 ======================== 292 293 While the default filesystem storage is suitable for most needs, there are many 294 other storage mechanisms that may be used, and situations that will require 295 special processing. In order to use Django in these environments, it's fairly 296 simple to write a new storage system, creating a wrapper around whatever 297 libraries are used to access your files, or simply customizing method calls on 298 an existing storage class. 299 300 If a storage system requires any configuration options to determine how it 301 should access the underlying storage mechanism or cusotmize its behavior in 302 other ways, those options should be specified in a particular way. Because the 303 default storage system is specified as a string, Django must be able to 304 instantiate it without any arguments, and any required arguments should be 305 specified as global settings, which can be referenced from the storage system. 306 For example:: 307 308 from django.conf import settings 309 from django.core.files.storage import Storage 310 311 class CustomStorage(Storage): 312 def __init__(self, option=settings.CUSTOM_STORAGE_OPTION): 313 ... 314 315 Every storage system will have all the methods described above, but there are a 316 few with have default behaviors that shouldn't be overridden by these subclasses 317 in most situations. Each of these has a different set of responsibilities that 318 the storage system is expected to fulfill: 319 320 * ``path()`` -- unless the class provides access to files that are also 321 accessible via the local filesystem, this should inherit the default behavior 322 of raising a ``NotImplementedError``. For those that do represent portions of 323 the filesystem, subclassing ``FileSystemStorage`` will typically be more 324 appropriate anyway. 325 326 * ``open()`` -- This provides some additional logic that isn't specific to 327 file retrieval, by supporting the ``mixin`` argument. Instead of overriding 328 this directly, storage systems should provide an ``_open()`` method as 329 described below. 330 331 * ``save()`` -- The ``name`` provided to this is actually more a preference, 332 because it will actually go through both ``get_valid_name()`` and 333 ``get_available_name()`` to determine what name the will actually be given. 334 It also returns the final name, taking care to adjust it to Unix-style paths. 335 Since these features aren't related to actually storing the file, subclasses 336 should instead provide a ``_save()`` method as described below. 337 338 The default beaviors for these methods are provided by the provided ``Storage`` 339 class, living at ``django.files.storage``. In addition, the two other methods 340 used by ``save()`` internally to determine the final filename, which have 341 default implementations, but can be overridden, and there are two other methods 342 that must be provided for all storage systems. 343 344 ``get_valid_name(name)`` 345 ------------------------ 346 347 Returns a filename suitable for use with the underlying storage system. The 348 ``name`` argument passed to this method is the original filename sent to the 349 server, after having any path information removed. Override this to customize 350 how non-standard characters are converted to safe filenames. 351 352 The code provided on ``Storage`` retains only alpha-numeric characters, periods 353 and underscores from the original filename, removing everything else. 354 355 ``get_available_name(name)`` 356 ---------------------------- 357 358 Returns a filename that is available in the storage mechanism, possibly taking 359 the provided filename into account. The ``name`` argument passed to this method 360 will have already cleaned to a filename valid for the storage system, according 361 to the ``get_valid_name()`` method described above. 362 363 The code provided on ``Storage`` simply appends underscores to the filename 364 until it finds one that's available in the destination directory. 365 366 ``_open(name, mode='rb')`` 367 -------------------------- 368 369 Returns an open ``File`` object that can be used to access the file's contents. 370 The ``mode`` represents all the same values as Python's own ``open()``, and 371 should be used to determine how the file can be accessed. See below for details 372 regarding how the returned ``File`` object should be behave for reading and 373 writing content. 374 375 ``_save(name, content)`` 376 ------------------------ 377 378 Stores the given content to the persistent storage backed by the class. The 379 ``name`` will already have gone through ``get_valid_name()`` and 380 ``get_available_name()``, and the ``content`` will be a ``File`` object itself. 381 This method has no return value. 382 383 Providing a ``File`` 384 -------------------- 385 386 Since the ``open()`` method returns a ``File`` object, it's expected that a 387 ``Storage`` subclass will provide a customized version that's designed to 388 interact with the underlying storage system. Many methods, such as ``read()``, 389 ``write()`` and ``close()``, should be overridden on this new ``File`` subclass, 390 so that it can transparently access the file's contents. -
docs/model-api.txt
224 224 ``FileField`` 225 225 ~~~~~~~~~~~~~ 226 226 227 A file-upload field. Has one **required** argument: 227 A file-upload field. Has two special arguments, of which the first is 228 **required**: 228 229 229 230 ====================== =================================================== 230 231 Argument Description 231 232 ====================== =================================================== 232 ``upload_to`` A local filesystem path that will be appended to 233 your ``MEDIA_ROOT`` setting to determine the 234 output of the ``get_<fieldname>_url()`` helper 235 function. 233 ``upload_to`` Required. A filesystem-style path that will be 234 prepended to the filename before being committed to 235 the final storage destination. 236 237 **New in Django development version** 238 239 This may also be a callable, such as a function, 240 which will be called to obtain the upload path, 241 including the filename. See below for details. 242 243 ``storage`` **New in Django development version** 244 245 Optional. A storage object, which handles the 246 storage and retrieval of your files. See `managing 247 files`_ for details on how to provide this object. 236 248 ====================== =================================================== 237 249 238 This path may contain `strftime formatting`_, which will be replaced by the 239 date/time of the file upload (so that uploaded files don't fill up the given 240 directory). 250 .. _managing files: ../files/ 241 251 252 The ``upload_to`` path may contain `strftime formatting`_, which will be 253 replaced by the date/time of the file upload (so that uploaded files don't fill 254 up the given directory). 255 256 **New in Django development version** 257 258 If a callable is provided for the ``upload_to`` argument, that callable must be 259 able to accept two arguments, and return a Unix-style path (with forward 260 slashes) to be passed along to the storage system. The two arguments that will 261 be passed are: 262 263 ====================== =================================================== 264 Argument Description 265 ====================== =================================================== 266 ``instance`` An instance of the model where the ``FileField`` is 267 defined. More specifically, this is the particular 268 instance where the current file is being attached. 269 270 **Note**: In most cases, this object will not have 271 been saved to the database yet, so if it uses the 272 default ``AutoField``, *it might not yet have a 273 value for its primary key field*. 274 275 ``filename`` The filename that was originally given to the file. 276 This may or may not be taken into account when 277 determining the final destination path. 278 ====================== =================================================== 279 242 280 The admin represents this field as an ``<input type="file">`` (a file-upload 243 281 widget). 244 282 245 Using a ``FileField`` or an ``ImageField`` (see below) in a model takes a few246 s teps:283 Using a ``FileField`` or an ``ImageField`` (see below) in a model without a 284 specified storage system takes a few steps: 247 285 248 286 1. In your settings file, you'll need to define ``MEDIA_ROOT`` as the 249 287 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
Property changes on: tests\modeltests\files ___________________________________________________________________ Name: svn:ignore + *.pyc
1 -
tests/modeltests/files/models.py
1 """ 2 42. Storing files according to a custom storage system 3 4 FileField and its variations can take a "storage" argument to specify how and 5 where files should be stored. 6 """ 7 8 import tempfile 9 10 from django.db import models 11 from django.core.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/admin_widgets/models.py
1 1 2 2 from django.conf import settings 3 3 from django.db import models 4 from django.core.files.storage import default_storage 4 5 5 6 class Member(models.Model): 6 7 name = models.CharField(max_length=100) … … 18 19 class Album(models.Model): 19 20 band = models.ForeignKey(Band) 20 21 name = models.CharField(max_length=100) 22 cover_art = models.ImageField(upload_to='albums') 21 23 22 24 def __unicode__(self): 23 25 return self.name … … 46 48 >>> print conditional_escape(w.render('test', datetime(2007, 12, 1, 9, 30))) 47 49 <p class="datetime">Date: <input value="2007-12-01" type="text" class="vDateField" name="test_0" size="10" /><br />Time: <input value="09:30:00" type="text" class="vTimeField" name="test_1" size="8" /></p> 48 50 51 >>> band = Band.objects.create(pk=1, name='Linkin Park') 52 >>> album = band.album_set.create(name='Hybrid Theory', cover_art=r'albums\hybrid_theory.jpg') 53 49 54 >>> w = AdminFileWidget() 50 >>> print conditional_escape(w.render('test', 'test'))51 Currently: <a target="_blank" href="%( MEDIA_URL)stest">test</a> <br />Change: <input type="file" name="test" />55 >>> print conditional_escape(w.render('test', album.cover_art)) 56 Currently: <a target="_blank" href="%(STORAGE_URL)salbums/hybrid_theory.jpg">albums\hybrid_theory.jpg</a> <br />Change: <input type="file" name="test" /> 52 57 53 >>> band = Band.objects.create(pk=1, name='Linkin Park')54 >>> album = band.album_set.create(name='Hybrid Theory')55 56 58 >>> rel = Album._meta.get_field('band').rel 57 59 >>> w = ForeignKeyRawIdWidget(rel) 58 60 >>> print conditional_escape(w.render('test', band.pk, attrs={})) … … 81 83 82 84 """ % { 83 85 'ADMIN_MEDIA_PREFIX': settings.ADMIN_MEDIA_PREFIX, 84 ' MEDIA_URL': settings.MEDIA_URL,86 'STORAGE_URL': default_storage.url(''), 85 87 }} -
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.utils import simplejson 10 10 from django.utils.hashcompat import sha_constructor 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/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
Property changes on: tests\regressiontests\storage ___________________________________________________________________ Name: svn:ignore + *.pyc
1 -
tests/regressiontests/storage/models.py
1 # Empty file to force tests to run -
tests/regressiontests/storage/tests.py
1 """ 2 Tests for the file storage mechanism 3 4 >>> import tempfile 5 >>> from django.core.files.storage import FileSystemStorage 6 >>> from django.core.files.base import ContentFile 7 8 >>> 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 """