文档管理

本文档描述了Django的文件访问API,用于用户上载的文件。较低级别的API足够通用,您可以将它们用于其他目的。如果要处理“静态文件”(JS、CSS等),请参见 如何管理静态文件(如图像、JavaScript、css) .

默认情况下,Django使用 MEDIA_ROOTMEDIA_URL 设置。下面的示例假设您正在使用这些默认值。

但是,Django提供了编写自定义 file storage systems 这允许您完全自定义django存储文件的位置和方式。本文档的后半部分描述了这些存储系统的工作方式。

在模型中使用文件

当你使用 FileFieldImageField ,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 指向相对于文件存储位置的路径 (MEDIA_ROOT 如果您使用的是默认的 FileSystemStorage ):

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

要将磁盘上的现有文件保存到 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 非图像数据属性,例如 heightwidth ,以及 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 实例在任何时候都需要表示一个文件。

大多数时候你会使用 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的默认文件存储是 ' :class:django.core.files.storage.FileSystemStorage ' 。如果您没有在 default 的关键字 STORAGES 设置,这是将使用的设置。

有关内置默认文件存储系统的详细信息,请参阅以下内容,然后参阅 如何编写自定义存储类 有关编写自己的文件存储系统的信息。

存储对象

尽管在大多数情况下,您会希望使用 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/photos 不管你的 MEDIA_ROOT 设置如下:

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)

Custom storage systems 以同样的方式工作:你可以把它们作为 storage 对A的论证 FileField .

使用可调用

您可以使用callable作为 storage 参数用于 FileFieldImageField . 这允许您在运行时修改使用的存储,例如为不同的环境选择不同的存储。

在加载models类时,将计算您的可调用项,并且必须返回 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)