管理文件

本页文档讲述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')

任何photo的实例都有一个 Car字段,你可以通过它来获取附加图片的详细信息:

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

例子中的File 对象是一个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/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)

Custom storage systems 以相同方式工作:你可以把它们作为storage参数传递给FileField