==============
Managing files
==============

**New in Django development version**

This document describes Django's file access APIs.

By default, Django stores files locally, using the ``MEDIA_ROOT`` and
``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`_
.. _settings: ../settings/

Using files in models
=====================

When you use a `FileField`_ or `ImageField`_, Django provides a set of APIs you can use to deal with that file.

.. _filefield: ../model-api/#filefield
.. _imagefield: ../model-api/#imagefield

Consider the following model, using a ``FileField`` to store a photo::

    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')

Any ``Car`` instance will have a ``photo`` attribute that you can use to get at
the details of the attached photo::

    >>> car = Car.object.get(name="57 Chevy")
    >>> car.photo
    <ImageFieldFile: chevy.jpg>
    >>> car.photo.name
    u'chevy.jpg'
    >>> car.photo.path
    u'/media/cars/chevy.jpg'
    >>> car.photo.url
    u'http://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.

The ``File`` object
===================

Internally, Django uses a ``django.core.files.File`` any time it needs to
represent a file. This object is a thin wrapper around Python's `built-in file
object`_ with some Django-specific additions.

.. _built-in file object: http://docs.python.org/lib/bltin-file-objects.html

Creating ``File`` instances
---------------------------

Most of the time you'll simply use a ``File`` that Django's given you (i.e. a
file attached to a model as above, or perhaps an `uploaded file`_).

.. _uploaded file: ../upload_handling/

If you need to construct a ``File`` yourself, the easiest way is to create one
using a Python built-in ``file`` object::

    >>> from django.core.files import File

    # Create a Python file object using open()
    >>> f = open('/tmp/hello.world', 'w')
    >>> myfile = File(f)

Now you can use any of the ``File`` attributes and methods defined below.

``File`` attributes and methods
-------------------------------

Django's ``File`` has the following attributes and methods:

``File.path``
~~~~~~~~~~~~~

The absolute path to the file's location on a local filesystem.

Custom `file storage systems`_ may not store files locally; files stored on
these systems will have a ``path`` of ``None``.

``File.url``
~~~~~~~~~~~~

The URL where the file can be retrieved. This is often useful in templates_; for
example, a bit of a template for displaying a ``Car`` (see above) might look
like::

    <img src='{{ car.photo.url }}' alt='{{ car.name }}' />

.. _templates: ../templates/

``File.size``
~~~~~~~~~~~~~

The size of the file in bytes.

``File.open(mode=None)``
~~~~~~~~~~~~~~~~~~~~~~~~

Open or reopen the file (which by definition also does ``File.seek(0)``). The
``mode`` argument allows the same values as Python's standard ``open()``.

When reopening a file, ``mode`` will override whatever mode the file was
originally opened with; ``None`` means to reopen with the original mode.

``File.read(num_bytes=None)``
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Read content from the file. The optional ``size`` is the number of bytes to
read; if not specified, the file will be read to the end.

``File.__iter__()``
~~~~~~~~~~~~~~~~~~~

Iterate over the file yielding one line at a time.

``File.chunks(chunk_size=None)``
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Iterate over the file yielding "chunks" of a given size. ``chunk_size`` defaults
to 64 KB.

This is especially useful with very large files since it allows them to be
streamed off disk and avoids storing the whole file in memory.

``File.multiple_chunks(chunk_size=None)``
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Returns ``True`` if the file is large enough to require multiple chunks to
access all of its content give some ``chunk_size``.

``File.write(content)``
~~~~~~~~~~~~~~~~~~~~~~~

Writes the specified content string to the file. Depending on the storage system
behind the scenes, this content might not be fully committed until ``close()``
is called on the file.

``File.close()``
~~~~~~~~~~~~~~~~

Close the file.

.. TODO: document the rest of the File methods.

Additional ``ImageField`` attributes
------------------------------------

``File.width`` and ``File.height``
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

These attributes provide the dimensions of the image.

Additional methods on files attached to objects
-----------------------------------------------

Any ``File`` that's associated with an object (as with ``Car.photo``, above)
will also have a couple of extra methods:

``File.save(name, content, save=True)``
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Saves a new file with the file name and contents provided. This will not replace
the existing file, but will create a new file and update the object to point to
it. If ``save`` is ``True``, the model's ``save()`` method will be called once
the file is saved. That is, these two lines::

    >>> car.photo.save('myphoto.jpg', contents, save=False)
    >>> car.save()

are the same as this one line::

    >>> car.photo.save('myphoto.jpg', contents, save=True)

``File.delete(save=True)``
~~~~~~~~~~~~~~~~~~~~~~~~~~

Remove the file from the model instance and delete the underlying file. The
``save`` argument works as above.

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 given by the `DEFAULT_FILE_STORAGE setting`_;
if you don't explicitly provide a storage system, this is the one that will be
used.

.. _default_file_storage setting: ../settings/#default-file-storage

The built-in filesystem storage class
-------------------------------------

Django ships with a built-in ``FileSystemStorage`` class (defined in
``django.core.files.storage``) which implements basic local filesystem file
storage. Its initializer takes two arguments:

======================  ===================================================
Argument                Description
======================  ===================================================
``location``            Optional. Absolute path to the directory that will
                        hold the files. If omitted, it will be set to the
                        value of your ``MEDIA_ROOT`` setting.
``base_url``            Optional. URL that serves the files stored at this
                        location. If omitted, it will default to the value
                        of your ``MEDIA_URL`` setting.
======================  ===================================================

For example, the following code will store uploaded files under
``/media/photos`` regardless of what your ``MEDIA_ROOT`` setting is::

    from django.db import models
    from django.core.files.storage import FileSystemStorage

    fs = FileSystemStorage(location='/media/photos')

    class Car(models.Model):
        ...
        photo = models.ImageField(storage=fs)

`Custom storage systems`_ work the same way: you can pass them in as the
``storage`` argument to a ``FileField``.

.. _custom storage systems: `writing a custom 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::

    >>> from django.core.files.storage import default_storage

    >>> path = default_storage.save('/path/to/file', 'new content')
    >>> path
    u'/path/to/file'

    >>> default_storage.filesize(path)
    11
    >>> default_storage.open(path).read()
    'new content'

    >>> default_storage.delete(path)
    >>> default_storage.exists(path)
    False

Storage objects define the following methods:

``Storage.exists(name)``
~~~~~~~~~~~~~~~~~~~~~~~~

``True`` if a file exists given some ``name``.

``Storage.path(name)``
~~~~~~~~~~~~~~~~~~~~~~

The local filesystem path where the file can be opened using Python's standard
``open()``. For storage systems that aren't accessible from the local
filesystem, this will raise ``NotImplementedError`` instead.

``Storage.size(name)``
~~~~~~~~~~~~~~~~~~~~~~

Returns the total size, in bytes, of the file referenced by ``name``.

``Storage.url(name)``
~~~~~~~~~~~~~~~~~~~~~

Returns the URL where the contents of the file referenced by ``name`` can be
accessed.

``Storage.open(name, mode='rb')``
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Opens the file given by ``name``. Note that although the returned file is
guaranteed to be a ``File`` object, it might actually be some subclass. In the
case of remote file storage this means that reading/writing could be quite slow,
so be warned.

``Storage.save(name, content)``
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Saves a new file using the storage system, preferably with the name specified.
If there already exists a file with this name ``name``, the storage system may
modify the filename as necessary to get a unique name. The actual name of the
stored file will be returned.

``Storage.delete(name)``
~~~~~~~~~~~~~~~~~~~~~~~~

Deletes the file referenced by ``name``. This method won't raise an exception if
the file doesn't exist.

Writing a custom storage system
===============================

If you need to provide custom file storage -- a common example is storing files
on some remote system -- you can do so by defining a custom storage class.
You'll need to follow these steps:

#. Your custom storage system must be a subclass of
   ``django.core.files.storage.Storage``::

        from django.core.files.storage import Storage

        class MyStorage(Storage):
            ...

#. Django must be able to instantiate your storage system without any arguments.
   This means that any settings should be taken from ``django.conf.settings``::

        from django.conf import settings
        from django.core.files.storage import Storage

        class MyStorage(Storage):
            def __init__(self, option=None):
                if not option:
                    option = settings.CUSTOM_STORAGE_OPTIONS
                ...

#. Your storage class must implement the ``_open()`` and ``_save()`` methods,
   along with any other methods appropriate to your storage class. See below for
   more on these methods.

   In addition, if your class provides local file storage, it must override
   the ``path()`` method.

Custom storage system methods
-----------------------------

Your custom storage system may override any of the storage methods explained
above in `storage objects`_. However, it's usually better to use the hooks
specifically designed for custom storage objects. These are:

``_open(name, mode='rb')``
~~~~~~~~~~~~~~~~~~~~~~~~~~

**Required**.

Called by ``Storage.open()``, this is the actual mechanism the storage class
uses to open the file. This must return a ``File`` object, though in most cases,
you'll want to return some subclass here that implements logic specific to the
backend storage system.

``_save(name, content)``
~~~~~~~~~~~~~~~~~~~~~~~~

Called by ``Storage.save()``. The ``name`` will already have gone through
``get_valid_name()`` and ``get_available_name()``, and the ``content`` will be a
``File`` object itself. No return value is expected.

``get_valid_name(name)``
------------------------

Returns a filename suitable for use with the underlying storage system. The
``name`` argument passed to this method is the original filename sent to the
server, after having any path information removed. Override this to customize
how non-standard characters are converted to safe filenames.

The code provided on ``Storage`` retains only alpha-numeric characters, periods
and underscores from the original filename, removing everything else.

``get_available_name(name)``
----------------------------

Returns a filename that is available in the storage mechanism, possibly taking
the provided filename into account. The ``name`` argument passed to this method
will have already cleaned to a filename valid for the storage system, according
to the ``get_valid_name()`` method described above.

The code provided on ``Storage`` simply appends underscores to the filename
until it finds one that's available in the destination directory.
