管理文件
默认情况下,Django 使用 MEDIA_ROOT
和MEDIA_URL
设置本地存储。下面的例子假设你在使用这些默认设置。
# 1、在模型中使用文件
当你使用 FileField
) 或 ImageField
时,Django 提供了一组处理文件的API。
考虑下面的模型,使用 ImageField 来存储照片:
from django.db import models
class Car(models.Model):
price = models.DecimalField(max_digits=5, decimal_places=2)
photo = models.ImageField(upload_to='cars') # 路径名字
2
3
4
5
任何 Car
实例将拥有一个 photo
属性,你可以使用它来获取附加照片的详情:
>>> car = Car.objects.get(pk=id)
>>> car.photo
<ImageFieldFile: cars/test.jpg>
>>> car.photo.name
'cars/test.jpg'
>>> car.photo.path
'/media/cars/test.jpg'
>>> car.photo.url
'<http://media.example.com/cars/test.jpg>'
2
3
4
5
6
7
8
9
car.photo
是一个 File
对象,这意味着它拥有下面所描述的所有方法和属性。
注意
文件在数据库中作为保存模型的一部分,因此在模型被保存之前,不能依赖磁盘上使用的实际文件名。
# 2、File 对象
在内部,Django 在任何需要表示文件的时候使用 django.core.files.File
大部分情况下你只需要使用 Django 提供的 File
(即附加到上述模型的文件或已经上传的文件)。
如果你需要自己构建 File
,最简单的方法是使用 Python 内置的 file
对象创建一个:
>>> from django.core.files import File
>>> f = open('/path/to/hello.txt', 'w')
>>> myfile = File(f)
2
3
4
现在你可以使用 File
类的任何属性和方法。
注意在这里创建的文件不会自动关闭。下面的方式可以用来自动关闭文件:
>>> from django.core.files import File
>>> with open('/path/to/hello.world', 'w') as f:
... myfile = File(f)
... myfile.write('Hello World')
...
>>> myfile.closed
True
>>> f.closed
True
2
3
4
5
6
7
8
9
10
在对大量对象进行循环访问文件字段时,关闭文件尤为重要。如果文件在访问后不能手动关闭,可能会出现文件描述符溢出的风险。
OSError: [Errno 24] Too many open files
# 3、文件存储
在后台,Django将如何以及在哪里存储文件的决策委托给文件存储系统。这个对象实际上理解文件系统、打开和读取文件等。
Django 的默认文件存储通过 DEFAULT_FILE_STORAGE
) 配置;如果你不显式地提供存储系统,这里会使用默认配置。
# 3.1 存储对象
虽然大部分时间你可以使用 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
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# 3.2 内置文件存储类
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)
2
3
4
5
6
7
8
1