Django 抽象出了一套“文件处理体系”,核心是:
- Django 所有文件类的基类
- 提供统一的接口用于:
使用FileField/ImageField来构造:
1 2 | classMyModel(models.Model):
file=models.FileField(upload_to='files/')
|
这个字段对文件内容不做存储,只存储文件路径字符串。
真正的文件保存由:
django.core.files.File
一套 Storage(默认本地文件系统)
1 | obj.file.save('result.txt', ContentFile('hello world'))
|
此时 Django 会:
把 ContentFile 写入本地或 OSS 或 S3
把保存后的路径写到数据库字段file
二、不同场景下该用哪种 Django 文件对象
场景 1:用户上传文件(常见 Web/DRF)
1 2 3 | defupload(request):
f=request.FILES['file']# InMemoryUploadedFile 或 TemporaryUploadedFile
print(f.name, f.size, f.content_type)
|
场景 2:动态生成一个文件(如 CSV/JSON/图片),并保存到 FileField
1 2 3 4 | fromdjango.core.files.baseimportContentFile
content="name,age\nTom,18\nJerry,20"
obj.file.save("data.csv", ContentFile(content))
|
场景 3:用 Python open 打开的本地文件,写入 FileField
1 2 3 4 | fromdjango.core.filesimportFile
withopen('local.txt','rb') as f:
obj.file.save('copy.txt',File(f))
|
三、几种文件存储的对应配置
1.本地存储:我就想存到服务器磁盘
Django 默认就是本地磁盘文件存储,用的类是:
1 | DEFAULT_FILE_STORAGE='django.core.files.storage.FileSystemStorage'
|
在settings.py里:
1 2 3 4 5 | importos
BASE_DIR=os.path.dirname(os.path.dirname(__file__))
MEDIA_ROOT=os.path.join(BASE_DIR,'media')# 真实文件保存路径
MEDIA_URL='/media/'# 浏览器访问前缀
|
模型配置:
1 2 | classMyModel(models.Model):
file=models.FileField(upload_to='uploads/')
|
最后
1 | obj.file.save('a.txt', ContentFile('hello'))
|
实际效果是:
- 文件会被保存到:
MEDIA_ROOT / uploads / a.txt - 例如:
/project_root/media/uploads/a.txt - 数据库里的字段只保存相对路径:
uploads/a.txt - 浏览器访问地址是:
MEDIA_URL + 'uploads/a.txt'→/media/uploads/a.txt
访问文件,只需要在url.py加一个静态路由:
1 2 3 4 5 6 | fromdjango.confimportsettings
fromdjango.conf.urls.staticimportstatic
urlpatterns=[
# ... 你的其他 URL
]+static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
|
2.上云存储:S3/OSS/COS/BOS 等
1)用现成库(如 django-storages + S3 为例),需要安装:
1 | pip install django-storages boto3
|
settings.py配置:
1 2 3 4 5 6 7 8 9 10 11 12 | INSTALLED_APPS=[
# ...
'storages',
]
DEFAULT_FILE_STORAGE='storages.backends.s3boto3.S3Boto3Storage'
AWS_ACCESS_KEY_ID='你的Key'
AWS_SECRET_ACCESS_KEY='你的Secret'
AWS_STORAGE_BUCKET_NAME='你的bucket名字'
AWS_S3_ENDPOINT_URL='https://s3.amazonaws.com'# 若用其他云厂商,写他们给的S3兼容endpoint
MEDIA_URL='https://你的bucket域名/'# 访问 URL 前缀
|
模型不需要改动:
1 2 | classMyModel(models.Model):
file=models.FileField(upload_to='files/')
|
业务代码:
1 | obj.file.save('a.txt', ContentFile('hello cloud'))
|
Django 会: