Django中如何显示文件大小?是否需为PDF创建模型?
问题与技术咨询
我在media目录下存放了一个供用户下载的PDF文件,目前有两个问题需要解决:
- 如何让用户看到该文件的大小,以便了解待下载文件的体积?
- 是否应当创建如下
models.py示例中的PersonalStatement模型来管理该PDF文件?处理此类场景的最佳方案是什么?
用户现有代码片段
models.py(暂未加入现有代码)
class PersonalStatement(models.Model): personal_statement = models.FileField(upload_to='personal_statement/') title = models.CharField(max_length=50)
views.py(下载视图)
def personal_statement_download(request): BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) filename = 'Writing-a-Personal-Statement.pdf' filepath = BASE_DIR + '/media/personal_statement/' + filename path = open(filepath, 'rb') mime_type, _ = mimetypes.guess_type(filepath) response = HttpResponse(path, content_type=mime_type) response['Content-Disposition'] = "attachment; filename=%s" % filename return response
urls.py
path('personal_statement/download/', views.personal_statement_download,name='personal_statement_download'),
templates/index.html
<a href="{% url 'personal_statement_download'%}" class="applyRightContentContainerSubDownloadLink"> Download File ⇩</a>
views.py(首页视图)
def home (request): return render(request, 'core/index.html')
解决方案
一、显示文件大小的实现方法
在首页视图中计算文件大小并格式化,传递给模板即可:
- 修改
home视图:
import os from django.conf import settings def home(request): # 用settings.MEDIA_ROOT替代硬编码路径,更规范 filename = 'Writing-a-Personal-Statement.pdf' filepath = os.path.join(settings.MEDIA_ROOT, 'personal_statement', filename) # 计算并格式化文件大小 if os.path.exists(filepath): file_size_bytes = os.path.getsize(filepath) # 根据大小自动切换KB/MB单位 if file_size_bytes >= 1024 * 1024: file_size = f"{file_size_bytes / (1024 * 1024):.2f} MB" else: file_size = f"{file_size_bytes / 1024:.2f} KB" else: file_size = "文件不存在" return render(request, 'core/index.html', {'file_size': file_size})
- 更新模板
index.html,显示文件大小:
<a href="{% url 'personal_statement_download'%}" class="applyRightContentContainerSubDownloadLink"> Download File ⇩ ({{ file_size }}) </a>
二、是否使用模型管理PDF?最佳方案分析
情况1:仅需管理单个固定PDF
如果这个PDF长期固定不变,不需要后台更新或上传,无需创建模型。只需优化现有代码的路径写法(避免硬编码BASE_DIR,改用settings.MEDIA_ROOT)即可:
优化后的下载视图:
import os import mimetypes from django.conf import settings from django.http import HttpResponse, Http404 def personal_statement_download(request): filename = 'Writing-a-Personal-Statement.pdf' filepath = os.path.join(settings.MEDIA_ROOT, 'personal_statement', filename) if not os.path.exists(filepath): return HttpResponse("文件不存在", status=404) # 用with语句自动关闭文件,更安全 with open(filepath, 'rb') as f: mime_type, _ = mimetypes.guess_type(filepath) response = HttpResponse(f, content_type=mime_type) response['Content-Disposition'] = f"attachment; filename={filename}" return response
情况2:需要动态管理PDF(后台上传/更新/多文件)
如果未来可能需要更换PDF、上传新版本,或管理多个同类文件,推荐创建PersonalStatement模型。优势在于:
- 可通过Django Admin后台直接操作文件,无需手动修改服务器文件系统
- 自动处理文件存储路径,避免硬编码
- 便于扩展字段(如文件描述、上传时间等)
实现步骤:
- 添加模型并执行迁移:
from django.db import models class PersonalStatement(models.Model): personal_statement = models.FileField(upload_to='personal_statement/') title = models.CharField(max_length=50, default="个人陈述指南") def __str__(self): return self.title # 封装文件大小计算方法 @property def file_size(self): size_bytes = self.personal_statement.size if size_bytes >= 1024 * 1024: return f"{size_bytes / (1024 * 1024):.2f} MB" else: return f"{size_bytes / 1024:.2f} KB"
- 修改首页视图从数据库取文件信息:
def home(request): # 假设仅需展示第一个文件 try: ps = PersonalStatement.objects.first() file_size = ps.file_size if ps else "无可用文件" except PersonalStatement.DoesNotExist: file_size = "无可用文件" return render(request, 'core/index.html', {'ps': ps, 'file_size': file_size})
- 更新下载视图通过模型获取文件:
from django.http import HttpResponse, Http404 from .models import PersonalStatement import mimetypes def personal_statement_download(request): try: ps = PersonalStatement.objects.first() file = ps.personal_statement.open('rb') mime_type, _ = mimetypes.guess_type(ps.personal_statement.path) # 提取文件名,避免路径干扰 filename = ps.personal_statement.name.split('/')[-1] response = HttpResponse(file, content_type=mime_type) response['Content-Disposition'] = f"attachment; filename={filename}" return response except PersonalStatement.DoesNotExist: raise Http404("文件不存在")
- 更新模板:
{% if ps %} <a href="{% url 'personal_statement_download'%}" class="applyRightContentContainerSubDownloadLink"> {{ ps.title }} ⇩ ({{ file_size }}) </a> {% else %} <p>暂无可用下载文件</p> {% endif %}
内容的提问来源于stack exchange,提问作者Joseph Ayemlo
相关产品推荐
相关产品推荐

