# Django 5.2.9 ドキュメント

# ファイルの管理

この文書では、ユーザがアップロードしたようなファイルに対する Django のファイルアクセス API について説明します。下位レベルの API は十分一般的なので、他の目的にも使えます。"静的ファイル" (JS や CSS など) を扱いたい場合は、 静的ファイル (画像、JavaScript、CSS など) を管理する を参照してください。

デフォルトでは、Django は `MEDIA_ROOT` と `MEDIA_URL` の設定を使って、ファイルをローカルに保存します。以下の例では、これらのデフォルトを使うことを前提にしています。

しかしながら、Djangoは、 Djangoがどこにどうやってファイルを保存するかの複雑なカスタムを許可するファイルストレージシステム file storage systems を提供しています。このドキュメントの後半では、それらのストレージシステムの働きについて説明します。

## モデルでファイルを使う

`FileField` や `ImageField` を使うと、 Django はそのファイルを扱うために使える API を提供します。

次のモデルを考えてみましょう。 `ImageField` を使って写真を保存します:

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

どの `Car` インスタンスにも `photo` 属性があり、それを使って添付写真の詳細を見ることができます:

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

このオブジェクト（例では `car.photo` ）は `File` オブジェクトであり、以下に説明するすべてのメソッドと属性を持ちます。

注釈

このファイルは、モデルをデータベースに保存する際に一緒に保存されるため、ディスク上で実際に使用されるファイル名は、モデルが保存されるまで当てになりません。

例えば、ファイルの `name` にファイルストレージの場所（デフォルトの `FileSystemStorage` を使用している場合は `MEDIA_ROOT` ）からの相対パスを指定することで、ファイル名を変更できます:

    >>> import os
    >>> from django.conf import settings
    >>> initial_path = car.photo.path
    >>> car.photo.name = "cars/chevy_ii.jpg"
    >>> new_path = os.path.join(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

ディスク上の既存のファイルを `FileField` に保存します:

    >>> 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()
    ...

注釈

`ImageField` のインスタンスでは、 `height`, `width`, `size` などの画像データ以外の属性は利用可能ですが、ベースとなる画像データは画像を開き直さなければ利用できません。たとえば:

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

## `File` オブジェクト

内部的には、Django はファイルを表現する必要があるときは常に `django.core.files.File` インスタンスを使います。

たいていの場合、Django から与えられた `ファイル` を使うことになるでしょう (つまり、上記のようにモデルに添付されたファイルや、アップロードされたファイルなど)。

自分で `File` を作成する必要がある場合、最も簡単な方法は Python 組み込みの `file` オブジェクトを使って作成することです:

    >>> from django.core.files import File

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

これで、 `File` クラスのドキュメント化された属性とメソッドのすべてを使えるようになりました。

この方法で作成されたファイルは、自動的に閉じないことに注意してください。ファイルを自動的に閉じるには、以下の方法が便利です:

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

ファイルを閉じることは、多数のオブジェクトをループしてファイルフィールドにアクセスする場合に特に重要です。ファイルにアクセスした後、ファイルを手動でクローズしないと、ファイル記述子が不足する危険性があります。これは以下のようなエラーにつながる可能性があります:

    OSError: [Errno 24] Too many open files

## ファイルストレージ

舞台裏では、Django はファイルをどこにどのように保存するかという決定を、ファイルストレージシステムに委譲します。これは、ファイルシステム、ファイルを開いたり読み込んだりといったことを実際に理解するオブジェクトです。

Django のデフォルトのファイルストレージは `'``django.core.files.storage.FileSystemStorage``'` です。もし `STORAGES` 設定の `default` キーでストレージシステムを明示的に指定しなければ、これが使われます。

組み込みのデフォルトのファイルストレージシステムの詳細については以下を参照してください。また、独自のファイルストレージシステムを作成する方法については カスタムのストレージクラスを書く を参照してください。

### ストレージ オブジェクト

ほとんどの場合、適切なストレージにそのファイルを委任する `File` オブジェクトを使用したいと思うでしょう。しかし、ファイルストレージシステムを直接使うこともできます。独自のファイルストレージクラスのインスタンスを作成するか、（たいていはより便利な）グローバルなデフォルトストレージシステムを使用できます。

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

ファイルストレージAPIについては ファイルストレージ API を参照してください。

### 組み込みのファイルシステムストレージクラス

Django には `django.core.files.storage.FileSystemStorage` クラスが同梱されており、基本的なローカルファイルシステムのファイルストレージを実装しています。

例えば、以下のコードは `MEDIA_ROOT` の設定に関係なく、アップロードされたファイルを `/media/photos` に保存します:

    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)

カスタムのストレージシステム も同じように動作します。 `FileField` の `storage` 引数として渡すことができます。

### 呼び出し可能オブジェクト (callable) を使う

呼び出し可能オブジェクトは `FileField` や `ImageField` の `storage` パラメータとして使用できます。これにより、実行時に使用するストレージを変更し、例えば環境ごとに異なるストレージを選択できます。

呼び出し可能オブジェクトは、モデルクラスが読み込まれたときに評価され、 `Storage` のインスタンスを返す必要があります。

例:

    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)

`STORAGES` 設定で定義されたストレージを設定するには `storages` を使います:

    from django.core.files.storage import storages

    def select_storage():
        return storages["mystorage"]

    class MyModel(models.Model):
        upload = models.FileField(storage=select_storage)

呼び出し可能オブジェクトはモデルクラスの読み込み時に評価されるため、テスト時に `STORAGES` 設定を上書きしたい場合は、代わりに `LazyObject` のサブクラスを使用する必要があります：

    from django.core.files.storage import storages
    from django.utils.functional import LazyObject

    class OtherStorage(LazyObject):
        def _setup(self):
            self._wrapped = storages["mystorage"]

    my_storage = OtherStorage()

    class MyModel(models.Model):
        upload = models.FileField(storage=my_storage)

`LazyObject` はストレージの評価を実際に必要になるまで遅延させるため、 `override_settings()` の効果を反映できるようになります：

    @override_settings(
        STORAGES={
            "mystorage": {
                "BACKEND": "django.core.files.storage.InMemoryStorage",
            }
        }
    )
    def test_storage():
        model = MyModel()
        assert isinstance(model.upload.storage, InMemoryStorage)