管理文件

本文档描述了Django的文件访问API,比如,用以对用户上传的文件进行访问。 较低级别的API足够普遍,您可以将其用于其他目的。 如果您想处理“静态文件”(JS,CSS等),请参阅Managing static files (e.g. images, JavaScript, CSS)

默认情况下,Django使用MEDIA_ROOTMEDIA_URL设置在本地存储文件。 下面的例子假设你正在使用这些默认值。

不过,Django提供了编写自定义文件存储系统的方法,可以让您完全自定义Django存储文件的位置和方式。 本文档的后半部分描述了这些存储系统是如何工作的。

在模型中使用文件

当你在模型中使用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')

任何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 – 是一个文件对象,意味着它有下面所述的所有方法与属性。

注意

该文件作为模型保存在数据库中的一部分进行保存,因此在保存模型之后,不能依赖磁盘上使用的实际文件名。

例如,您可以通过将文件的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

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设置给出;如果您没有明确提供存储系统,则会使用这个存储系统。

有关内置默认文件存储系统的详细信息,请参阅Writing a custom storage system以获取有关编写自己的文件存储系统的信息。

存储对象

尽管大多数情况下您需要使用一个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的File storage API

内置的文件系统存储类

Django附带一个django.core.files.storage.FileSystemStorage类,它实现了基本的本地文件系统文件存储。

例如,无论您的MEDIA_ROOT设置如何,以下代码都会将上传的文件存储在/media/photos下:

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.