本文檔描述了Django的文件訪問API,用於例如用戶上傳的文件。較低級別的API足夠通用,您可以將它們用於其他目的。如果要處理“靜態文件”(JS,CSS等),請參閱 管理靜態文件(例如圖像,JavaScript,CSS)。
默認情況下,Django使用MEDIA_ROOT和 MEDIA_URL設置在本地存儲文件。以下示例假設您使用這些默認值。
但是,Django提供了編寫自定義文件存儲系統的方法,允許您完全自定義Django存儲文件的位置和方式。本文檔的後半部分描述了這些存儲系統的工作原理。
1. 在模型中使用文件
當您使用 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'
譯者注:
本地測試使用ImageField會報錯,沒有安裝Pillow庫
該對象 - 示例中的 car.photo - 是一個File對象,這意味着它具有下面描述的所有方法和屬性。
注意
該文件是作爲模型中的一部分保存在數據庫中的,因此在保存模型之前,不能依賴磁盤上使用的實際文件名。
例如,您可以通過這樣一種方式修改文件名,將文件名設置爲相對於存儲位置(如果使用默認的 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
2. File對象
在內部,Django 在需要表示文件的任何時候都使用django.core.files.File實例。
大多數情況下,你只需使用Django給你的File(例如,即上面Car模型的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
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('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。
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)