Skip to main content

管理文件

本文档描述了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')

任何 Car 实例都将具有 photo 属性,您可以使用它来获取附加的照片的详细信息:

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

File 对象

在内部,Django在需要表示文件的任何时候使用 django.core.files.File 实例。

大多数时候,你只需使用Django给你的 File (即附加到上面的模型的文件,或者上传的文件)。

如果你需要自己构建一个 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

当在大量对象上循环访问文件字段时,关闭文件尤其重要。如果文件在访问它们后没有手动关闭,则可能出现文件描述符耗尽的风险。这可能会导致以下错误:

IOError: [Errno 24] Too many open files

文件存储

在幕后,Django委派关于如何和在哪里将文件存储到文件存储系统的决定。这是实际理解文件系统,打开和读取文件等的对象。

Django的默认文件存储由 DEFAULT_FILE_STORAGE 设置给出;如果您未明确提供存储系统,则将使用该存储系统。

有关内置默认文件存储系统的详细信息,请参阅下文,有关编写自己的文件存储系统的信息,请参阅 编写自定义存储系统

存储对象

虽然大多数情况下,您需要使用 File 对象(它委托适当的存储为该文件),您可以直接使用文件存储系统。您可以创建一些自定义文件存储类的实例,或者(通常更有用),可以使用全局默认存储系统:

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

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

>>> default_storage.size(path)
11
>>> default_storage.open(path).read()
'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.db import models
from django.core.files.storage import FileSystemStorage

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

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

自定义存储系统 的工作方式相同:您可以将它们作为 storage 参数传递给 FileField