文章目录
- def setup_django(): BASE_DIR = Path(__file__).resolve().parent.parent.parent sys.path.append(str(BASE_DIR)) os.environ.setdefault(‘DJANGO_SETTINGS_MODULE’, ‘yunCoolCinema.settings’) django.setup() from django.conf import settings return settings 作用:使脚本能访问 Django 模型和设置 注意:根据项目结构调整路径层级
- def upload_file_to_model(model, file_path, field_name=’avatar’, **kwargs): file_field = getattr(model, field_name) with open(file_path, ‘rb’) as f: file_field.save( Path(file_path).name, # 文件名 File(f), # 文件内容 save=True # 保存模型 ) 核心方法:file_field.save() 参数说明: 第一个参数:保存的文件名 第二个参数:File 对象 save=True:自动保存模型到数据库
- # 上传后文件保存位置 file_path = model.avatar.path # 物理路径: MEDIA_ROOT/portrait/filename.jpg file_url = model.avatar.url # 访问URL: MEDIA_URL/portrait/filename.jpg 存储位置:MEDIA_ROOT/upload_to/filename 自动处理:Django 自动处理文件存储和路径记录
- # settings.py # 媒体文件配置 MEDIA_URL = ‘/media/’ # 访问URL MEDIA_ROOT = os.path.join(BASE_DIR, ‘media’) # 文件存储路径
- # urls.py from django.conf import settings from django.conf.urls.static import static urlpatterns = [ # …其他URL… ] if settings.DEBUG: urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
- # 自定义文件名 def custom_filename(instance, filename): “””生成自定义文件名””” return f”portrait/{instance.id}_{filename}” # 在模型中 avatar = models.ImageField(upload_to=custom_filename)
- import uuid def unique_filename(instance, filename): “””生成唯一文件名””” ext = filename.split(‘.’)[-1] return f”portrait/{uuid.uuid4().hex}.{ext}”
- def bulk_upload(models, file_map, field_name): “””批量上传文件””” for model in models: if model.name in file_map: upload_file_to_model(model, file_map[model.name], field_name)
- from tqdm import tqdm # 在循环中使用 for actor_name, file_path in tqdm(file_map.items(), desc=”上传文件”): # 上传逻辑
- from django.core.exceptions import ValidationError def validate_image(file_path): “””验证图片文件””” # 检查文件大小 if file_path.stat().st_size > 5 * 1024 * 1024: # 5MB raise ValidationError(“文件大小超过限制”) # 检查文件类型 if file_path.suffix.lower() not in [‘.jpg’, ‘.jpeg’, ‘.png’]: raise ValidationError(“不支持的文件类型”)
- try: upload_file_to_model(actor, file_path) except OSError as e: logger.error(‘文件操作错误: %s’, str(e)) except django.db.utils.IntegrityError as e: logger.error(‘数据库错误: %s’, str(e)) except Exception as e: logger.exception(‘未知错误’)
- # settings.py DEFAULT_FILE_STORAGE = ‘storages.backends.s3boto3.S3Boto3Storage’ AWS_ACCESS_KEY_ID = ‘your-access-key’ AWS_SECRET_ACCESS_KEY = ‘your-secret-key’ AWS_STORAGE_BUCKET_NAME = ‘your-bucket-name’ AWS_S3_REGION_NAME = ‘your-region’
- def cleanup_old_file(model, field_name): “””清理旧文件””” old_file = getattr(model, field_name) if old_file and old_file.name: old_file.delete(save=False) # 删除文件但不保存模型
- from django.core.cache import cache def get_cached_model(model_class, pk): “””获取缓存模型””” cache_key = f”{model_class.__name__}_{pk}” model = cache.get(cache_key) if not model: model = model_class.objects.get(pk=pk) cache.set(cache_key, model, timeout=60 * 60) # 缓存1小时 return model
- # 创建虚拟环境 python -m venv .venv source .venv/bin/activate # Linux/macOS ..venvScriptsactivate # Windows # 安装依赖 pip install django tqdm
- project/ ├── manage.py ├── media/ # 上传的文件存储位置 (自动创建) ├── data/ # 原始文件目录 │ └── portrait/ │ ├── 张艺谋.jpg │ └── 巩俐.png ├── scripts/ │ └── upload_files.py # 上传脚本 └── yunCoolCinema/ ├── settings.py ├── urls.py └── actors/ ├── models.py └── …
- python scripts/upload_files.py
- # 在Django shell中验证 from actors.models import Actor actor = Actor.objects.get(name=”张艺谋”) print(actor.avatar.url) # 输出: /media/portrait/张艺谋.jpg
- 文件保存在 MEDIA_ROOT/upload_to/ 目录下,其中: MEDIA_ROOT 在 settings.py 中定义 upload_to 在模型字段中定义
- 在模板中使用: <img src=”{{ actor.avatar.url }}” alt=”{{ actor.name }}”> 确保在开发环境中配置了媒体文件服务。
- 使用 uuid 生成唯一文件名 添加模型ID作为前缀 使用时间戳
- # 更新文件时自动删除旧文件 def save(self, *args, **kwargs): if self.pk: # 检查是否是更新操作 old = Actor.objects.get(pk=self.pk) if old.avatar != self.avatar: # 检查头像是否更改 old.avatar.delete(save=False) # 删除旧文件 super().save(*args, **kwargs)
目录
- 一、核心概念
- 1. Django 文件字段
- 2. 媒体文件系统
- 二、完整脚本示例
- 三、关键步骤详解
- 1. 配置 Django 环境
- 2. 文件上传核心函数
- 3. 路径保存机制
- 四、路径保存注意事项
- 1. 正确配置 settings.py
- 2. URL 配置
- 3. 文件名处理技巧
- 4. 避免路径冲突
- 五、高级功能扩展
- 1. 批量上传优化
- 2. 添加进度显示
- 3. 文件验证
- 4. 错误处理增强
- 六、生产环境最佳实践
- 1. 使用云存储
- 2. 添加文件清理
- 3. 使用缓存加速
- 七、完整工作流程
- 1. 准备环境
- 2. 文件目录结构
- 3. 运行脚本
- 4. 验证结果
- 八、常见问题解答
- Q1: 文件保存在哪里?
- Q2: 如何访问上传的文件?
- Q3: 文件名冲突怎么办?
- Q4: 如何删除旧文件?
- 九、总结
- ImageField:用于存储图片文件
- FileField:用于存储任意文件类型
- upload_to:指定文件存储的子目录
- MEDIA_ROOT:文件在服务器上的存储路径
- MEDIA_URL:文件访问的 URL 前缀
- 文件保存流程:
文件上传 → 保存到 MEDIA_ROOT/upload_to/ → 数据库记录路径
文件上传 → 保存到 MEDIA_ROOT/upload_to/ → 数据库记录路径
"""
Django 脚本上传文件到 ImageField 完整示例
"""
import os
import sys
import django
from pathlib import Path
from django.core.files import File
import logging
# 配置日志
logger = logging.getLogger(__name__)
logging.basicConfig(
level=logging.INFO,
format='%(asctime)s - %(name)s - %(levelname)s - %(message)s',
handlers=[
logging.FileHandler('upload_script.log'),
logging.StreamHandler()
]
)
def setup_django():
"""配置 Django 环境"""
# 获取项目根目录
BASE_DIR = Path(__file__).resolve().parent.parent.parent
# 添加到系统路径
sys.path.append(str(BASE_DIR))
# 设置 Django 环境变量
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'yunCoolCinema.settings')
# 初始化 Django
django.setup()
# 导入 Django 设置
from django.conf import settings
return settings
def upload_file_to_model(model, file_path, field_name='avatar', **kwargs):
"""
上传文件到模型字段
:param model: 模型实例
:param file_path: 文件路径
:param field_name: 字段名称
:param kwargs: 模型过滤条件
:return: 更新后的模型实例
"""
# 获取文件字段
file_field = getattr(model, field_name)
# 打开文件
with open(file_path, 'rb') as f:
# 保存文件到字段
file_field.save(
Path(file_path).name, # 文件名
File(f), # 文件内容,转换成django内部的文件对象
save=True # 保存模型
)
logger.info('文件已上传: %s -> %s', file_path, file_field.path)
return model
def main():
"""主函数"""
# 1. 设置 Django 环境
settings = setup_django()
logger.info('Django 环境设置完成')
# 2. 导入模型
from actors.models import Actor
# 3. 设置文件目录
file_dir = Path('data/portrait') # 文件源目录
if not file_dir.exists():
logger.error('文件目录不存在: %s', file_dir)
return
# 4. 获取演员和文件映射
# 假设文件名格式: {演员姓名}.jpg
file_map = {}
for file_path in file_dir.glob('*.*'):
if file_path.suffix.lower() in ['.jpg', '.jpeg', '.png']:
actor_name = file_path.stem # 文件名(不带扩展名)
file_map[actor_name] = file_path
# 5. 批量上传文件
success_count = 0
for actor_name, file_path in file_map.items():
try:
# 获取演员对象
actor = Actor.objects.get(name=actor_name)
# 上传文件
upload_file_to_model(actor, file_path)
success_count += 1
except Actor.DoesNotExist:
logger.warning('演员不存在: %s', actor_name)
except Exception as e:
logger.error('上传失败: %s - %s', actor_name, str(e))
logger.info('文件上传完成: 成功 %d 个', success_count)
if __name__ == "__main__":
main()
def setup_django():
BASE_DIR = Path(__file__).resolve().parent.parent.parent
sys.path.append(str(BASE_DIR))
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'yunCoolCinema.settings')
django.setup()
from django.conf import settings
return settings
- 作用:使脚本能访问 Django 模型和设置
- 注意:根据项目结构调整路径层级
def upload_file_to_model(model, file_path, field_name='avatar', **kwargs):
file_field = getattr(model, field_name)
with open(file_path, 'rb') as f:
file_field.save(
Path(file_path).name, # 文件名
File(f), # 文件内容
save=True # 保存模型
)
- 核心方法:
file_field.save()
- 参数说明:
- 第一个参数:保存的文件名
- 第二个参数:
File 对象
save=True:自动保存模型到数据库
file_field.save()- 第一个参数:保存的文件名
- 第二个参数:
File对象 save=True:自动保存模型到数据库
# 上传后文件保存位置
file_path = model.avatar.path # 物理路径: MEDIA_ROOT/portrait/filename.jpg
file_url = model.avatar.url # 访问URL: MEDIA_URL/portrait/filename.jpg
- 存储位置:
MEDIA_ROOT/upload_to/filename
- 自动处理:Django 自动处理文件存储和路径记录
MEDIA_ROOT/upload_to/filename
# settings.py
# 媒体文件配置
MEDIA_URL = '/media/' # 访问URL
MEDIA_ROOT = os.path.join(BASE_DIR, 'media') # 文件存储路径
# urls.py
from django.conf import settings
from django.conf.urls.static import static
urlpatterns = [
# ...其他URL...
]
if settings.DEBUG:
urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
# 自定义文件名
def custom_filename(instance, filename):
"""生成自定义文件名"""
return f"portrait/{instance.id}_{filename}"
# 在模型中
avatar = models.ImageField(upload_to=custom_filename)
import uuid
def unique_filename(instance, filename):
"""生成唯一文件名"""
ext = filename.split('.')[-1]
return f"portrait/{uuid.uuid4().hex}.{ext}"
def bulk_upload(models, file_map, field_name):
"""批量上传文件"""
for model in models:
if model.name in file_map:
upload_file_to_model(model, file_map[model.name], field_name)
from tqdm import tqdm
# 在循环中使用
for actor_name, file_path in tqdm(file_map.items(), desc="上传文件"):
# 上传逻辑
from django.core.exceptions import ValidationError
def validate_image(file_path):
"""验证图片文件"""
# 检查文件大小
if file_path.stat().st_size > 5 * 1024 * 1024: # 5MB
raise ValidationError("文件大小超过限制")
# 检查文件类型
if file_path.suffix.lower() not in ['.jpg', '.jpeg', '.png']:
raise ValidationError("不支持的文件类型")
try:
upload_file_to_model(actor, file_path)
except OSError as e:
logger.error('文件操作错误: %s', str(e))
except django.db.utils.IntegrityError as e:
logger.error('数据库错误: %s', str(e))
except Exception as e:
logger.exception('未知错误')
# settings.py
DEFAULT_FILE_STORAGE = 'storages.backends.s3boto3.S3Boto3Storage'
AWS_ACCESS_KEY_ID = 'your-access-key'
AWS_SECRET_ACCESS_KEY = 'your-secret-key'
AWS_STORAGE_BUCKET_NAME = 'your-bucket-name'
AWS_S3_REGION_NAME = 'your-region'
def cleanup_old_file(model, field_name):
"""清理旧文件"""
old_file = getattr(model, field_name)
if old_file and old_file.name:
old_file.delete(save=False) # 删除文件但不保存模型
from django.core.cache import cache
def get_cached_model(model_class, pk):
"""获取缓存模型"""
cache_key = f"{model_class.__name__}_{pk}"
model = cache.get(cache_key)
if not model:
model = model_class.objects.get(pk=pk)
cache.set(cache_key, model, timeout=60 * 60) # 缓存1小时
return model
# 创建虚拟环境
python -m venv .venv
source .venv/bin/activate # Linux/macOS
..venvScriptsactivate # Windows
# 安装依赖
pip install django tqdm
project/
├── manage.py
├── media/ # 上传的文件存储位置 (自动创建)
├── data/ # 原始文件目录
│ └── portrait/
│ ├── 张艺谋.jpg
│ └── 巩俐.png
├── scripts/
│ └── upload_files.py # 上传脚本
└── yunCoolCinema/
├── settings.py
├── urls.py
└── actors/
├── models.py
└── ...
python scripts/upload_files.py
# 在Django shell中验证
from actors.models import Actor
actor = Actor.objects.get(name="张艺谋")
print(actor.avatar.url) # 输出: /media/portrait/张艺谋.jpg
文件保存在 MEDIA_ROOT/upload_to/ 目录下,其中:
MEDIA_ROOT在 settings.py 中定义upload_to在模型字段中定义
在模板中使用:
<img src="{{ actor.avatar.url }}" alt="{{ actor.name }}">
确保在开发环境中配置了媒体文件服务。
- 使用
uuid 生成唯一文件名
- 添加模型ID作为前缀
- 使用时间戳
uuid 生成唯一文件名
# 更新文件时自动删除旧文件
def save(self, *args, **kwargs):
if self.pk: # 检查是否是更新操作
old = Actor.objects.get(pk=self.pk)
if old.avatar != self.avatar: # 检查头像是否更改
old.avatar.delete(save=False) # 删除旧文件
super().save(*args, **kwargs)
通过本教程,您学会了:
- 如何配置 Django 脚本环境
- 如何通过脚本上传文件到 ImageField
- 文件保存路径的处理机制
- 生产环境的最佳实践
关键点:
- 使用
file_field.save()方法上传文件 - 确保
MEDIA_ROOT正确配置 - 文件将自动保存到
MEDIA_ROOT/upload_to/目录 - 数据库记录相对路径(相对于
MEDIA_ROOT)
通过实现这些技术,您可以轻松地通过脚本将文件上传到 Django 的 ImageField 字段,并确保文件保存在正确的位置。
以上就是Django通过脚本上传文件的详细操作指南的详细内容,更多关于Django脚本上传文件的资料请关注风君子博客其它相关文章!
您可能感兴趣的文章:
- Django+simpleui实现文件上传预览功能(详细过程)
- Python web实战教程之Django文件上传和处理详解
- 使用Django+Vue编写一个文件上传器
- Django+Vue实现文件上传下载的项目实践
- vue与django(drf)实现文件上传下载功能全过程