123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274 |
- ==============
- Managing files
- ==============
- This document describes Django's file access APIs for files such as those
- uploaded by a user. The lower level APIs are general enough that you could use
- them for other purposes. If you want to handle "static files" (JS, CSS, etc.),
- see :doc:`/howto/static-files/index`.
- By default, Django stores files locally, using the :setting:`MEDIA_ROOT` and
- :setting:`MEDIA_URL` settings. The examples below assume that you're using these
- defaults.
- However, Django provides ways to write custom `file storage systems`_ that
- allow you to completely customize where and how Django stores files. The
- second half of this document describes how these storage systems work.
- .. _file storage systems: `File storage`_
- Using files in models
- =====================
- When you use a :class:`~django.db.models.FileField` or
- :class:`~django.db.models.ImageField`, Django provides a set of APIs you can use
- to deal with that file.
- Consider the following model, using an :class:`~django.db.models.ImageField` to
- store a photo::
- from django.db import models
- class Car(models.Model):
- name = models.CharField(max_length=255)
- price = models.DecimalField(max_digits=5, decimal_places=2)
- photo = models.ImageField(upload_to="cars")
- specs = models.FileField(upload_to="specs")
- Any ``Car`` instance will have a ``photo`` attribute that you can use to get at
- the details of the attached photo:
- .. code-block:: pycon
- >>> car = Car.objects.get(name="57 Chevy")
- >>> car.photo
- <ImageFieldFile: cars/chevy.jpg>
- >>> car.photo.name
- 'cars/chevy.jpg'
- >>> car.photo.path
- '/media/cars/chevy.jpg'
- >>> car.photo.url
- 'https://media.example.com/cars/chevy.jpg'
- This object -- ``car.photo`` in the example -- is a ``File`` object, which means
- it has all the methods and attributes described below.
- .. note::
- The file is saved as part of saving the model in the database, so the actual
- file name used on disk cannot be relied on until after the model has been
- saved.
- For example, you can change the file name by setting the file's
- :attr:`~django.core.files.File.name` to a path relative to the file storage's
- location (:setting:`MEDIA_ROOT` if you are using the default
- :class:`~django.core.files.storage.FileSystemStorage`):
- .. code-block:: pycon
- >>> import os
- >>> from django.conf import settings
- >>> initial_path = car.photo.path
- >>> car.photo.name = "cars/chevy_ii.jpg"
- >>> new_path = settings.MEDIA_ROOT + car.photo.name
- >>> # Move the file on the filesystem
- >>> os.rename(initial_path, new_path)
- >>> car.save()
- >>> car.photo.path
- '/media/cars/chevy_ii.jpg'
- >>> car.photo.path == new_path
- True
- To save an existing file on disk to a :class:`~django.db.models.FileField`:
- .. code-block:: pycon
- >>> from pathlib import Path
- >>> from django.core.files import File
- >>> path = Path("/some/external/specs.pdf")
- >>> car = Car.objects.get(name="57 Chevy")
- >>> with path.open(mode="rb") as f:
- ... car.specs = File(f, name=path.name)
- ... car.save()
- ...
- .. note::
- While :class:`~django.db.models.ImageField` non-image data attributes, such
- as ``height``, ``width``, and ``size`` are available on the instance, the
- underlying image data cannot be used without reopening the image. For
- example:
- .. code-block:: pycon
- >>> from PIL import Image
- >>> car = Car.objects.get(name="57 Chevy")
- >>> car.photo.width
- 191
- >>> car.photo.height
- 287
- >>> image = Image.open(car.photo)
- # Raises ValueError: seek of closed file.
- >>> car.photo.open()
- <ImageFieldFile: cars/chevy.jpg>
- >>> image = Image.open(car.photo)
- >>> image
- <PIL.JpegImagePlugin.JpegImageFile image mode=RGB size=191x287 at 0x7F99A94E9048>
- The ``File`` object
- ===================
- Internally, Django uses a :class:`django.core.files.File` instance any time it
- needs to represent a file.
- Most of the time you'll use a ``File`` that Django's given you (i.e. a file
- attached to a model as above, or perhaps an uploaded file).
- If you need to construct a ``File`` yourself, the easiest way is to create one
- using a Python built-in ``file`` object:
- .. code-block:: pycon
- >>> from django.core.files import File
- # Create a Python file object using open()
- >>> f = open("/path/to/hello.world", "w")
- >>> myfile = File(f)
- Now you can use any of the documented attributes and methods
- of the :class:`~django.core.files.File` class.
- Be aware that files created in this way are not automatically closed.
- The following approach may be used to close files automatically:
- .. code-block:: pycon
- >>> from django.core.files import File
- # Create a Python file object using open() and the with statement
- >>> with open("/path/to/hello.world", "w") as f:
- ... myfile = File(f)
- ... myfile.write("Hello World")
- ...
- >>> myfile.closed
- True
- >>> f.closed
- True
- Closing files is especially important when accessing file fields in a loop
- over a large number of objects. If files are not manually closed after
- accessing them, the risk of running out of file descriptors may arise. This
- may lead to the following error:
- .. code-block:: pytb
- OSError: [Errno 24] Too many open files
- File storage
- ============
- Behind the scenes, Django delegates decisions about how and where to store files
- to a file storage system. This is the object that actually understands things
- like file systems, opening and reading files, etc.
- Django's default file storage is
- ``'``:class:`django.core.files.storage.FileSystemStorage`\ ``'``. If you don't
- explicitly provide a storage system in the ``default`` key of the
- :setting:`STORAGES` setting, this is the one that will be used.
- See below for details of the built-in default file storage system, and see
- :doc:`/howto/custom-file-storage` for information on writing your own file
- storage system.
- Storage objects
- ---------------
- Though most of the time you'll want to use a ``File`` object (which delegates to
- the proper storage for that file), you can use file storage systems directly.
- You can create an instance of some custom file storage class, or -- often more
- useful -- you can use the global default storage system:
- .. code-block:: pycon
- >>> from django.core.files.base import ContentFile
- >>> from django.core.files.storage import default_storage
- >>> path = default_storage.save("path/to/file", ContentFile(b"new content"))
- >>> path
- 'path/to/file'
- >>> default_storage.size(path)
- 11
- >>> default_storage.open(path).read()
- b'new content'
- >>> default_storage.delete(path)
- >>> default_storage.exists(path)
- False
- See :doc:`/ref/files/storage` for the file storage API.
- .. _builtin-fs-storage:
- The built-in filesystem storage class
- -------------------------------------
- Django ships with a :class:`django.core.files.storage.FileSystemStorage` class
- which implements basic local filesystem file storage.
- For example, the following code will store uploaded files under
- ``/media/photos`` regardless of what your :setting:`MEDIA_ROOT` setting is::
- from django.core.files.storage import FileSystemStorage
- from django.db import models
- fs = FileSystemStorage(location="/media/photos")
- class Car(models.Model):
- ...
- photo = models.ImageField(storage=fs)
- :doc:`Custom storage systems </howto/custom-file-storage>` work the same way:
- you can pass them in as the ``storage`` argument to a
- :class:`~django.db.models.FileField`.
- Using a callable
- ----------------
- You can use a callable as the :attr:`~django.db.models.FileField.storage`
- parameter for :class:`~django.db.models.FileField` or
- :class:`~django.db.models.ImageField`. This allows you to modify the used
- storage at runtime, selecting different storages for different environments,
- for example.
- Your callable will be evaluated when your models classes are loaded, and must
- return an instance of :class:`~django.core.files.storage.Storage`.
- For example::
- from django.conf import settings
- from django.db import models
- from .storages import MyLocalStorage, MyRemoteStorage
- def select_storage():
- return MyLocalStorage() if settings.DEBUG else MyRemoteStorage()
- class MyModel(models.Model):
- my_file = models.FileField(storage=select_storage)
- In order to set a storage defined in the :setting:`STORAGES` setting you can
- use :data:`~django.core.files.storage.storages`::
- from django.core.files.storage import storages
- def select_storage():
- return storages["mystorage"]
- class MyModel(models.Model):
- upload = models.FileField(storage=select_storage)
|