You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Django中如何显示文件大小?是否需为PDF创建模型?

问题与技术咨询

我在media目录下存放了一个供用户下载的PDF文件,目前有两个问题需要解决:

  1. 如何让用户看到该文件的大小,以便了解待下载文件的体积?
  2. 是否应当创建如下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 &#8681;</a>

views.py(首页视图)

def home (request):
    return render(request, 'core/index.html')

解决方案

一、显示文件大小的实现方法

在首页视图中计算文件大小并格式化,传递给模板即可:

  1. 修改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})
  1. 更新模板index.html,显示文件大小:
<a href="{% url 'personal_statement_download'%}" class="applyRightContentContainerSubDownloadLink">
    Download File &#8681; ({{ 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后台直接操作文件,无需手动修改服务器文件系统
  • 自动处理文件存储路径,避免硬编码
  • 便于扩展字段(如文件描述、上传时间等)

实现步骤:

  1. 添加模型并执行迁移:
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"
  1. 修改首页视图从数据库取文件信息:
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})
  1. 更新下载视图通过模型获取文件:
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("文件不存在")
  1. 更新模板:
{% if ps %}
<a href="{% url 'personal_statement_download'%}" class="applyRightContentContainerSubDownloadLink">
    {{ ps.title }} &#8681; ({{ file_size }})
</a>
{% else %}
<p>暂无可用下载文件</p>
{% endif %}

内容的提问来源于stack exchange,提问作者Joseph Ayemlo

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.07 00:44:52