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

如何在Django项目实现PDF/Doc文件上传下载?求Admin/模板简化方案

简便实现Django目录文件下载的方案

嘿,我之前也做过类似的需求,你现在写的单个文件下载视图确实能跑,但用Django Admin或者优化前端的方式,能省不少重复代码,还更易维护!下面给你两个实用的方案:

方案一:用Django Admin管理可下载目录(自动打包成ZIP)

这个方案最适合管理员上传/维护目录,用户直接下载整个目录的压缩包,不用手动处理单个文件。

步骤1:创建模型管理目录元数据

首先定义一个模型,用来记录目录的基本信息(比如名称、描述、存储路径):

# models.py
from django.db import models

class DownloadableDirectory(models.Model):
    name = models.CharField(max_length=255, verbose_name="目录名称")
    description = models.TextField(blank=True, verbose_name="目录描述")
    directory_path = models.CharField(max_length=500, verbose_name="媒体目录路径")  # 示例值:"downloads/brochures/"
    created_at = models.DateTimeField(auto_now_add=True)

    def __str__(self):
        return self.name

步骤2:注册到Django Admin

把这个模型加到Admin里,管理员就能直接维护目录信息了:

# admin.py
from django.contrib import admin
from .models import DownloadableDirectory

admin.site.register(DownloadableDirectory)

步骤3:写一个自动打包ZIP的视图

不用再写单个文件的逻辑,直接把指定目录打包成ZIP返回给用户:

# views.py
import os
import zipfile
from django.http import HttpResponse
from django.conf import settings
from .models import DownloadableDirectory

def download_directory(request, dir_id):
    dir_obj = DownloadableDirectory.objects.get(id=dir_id)
    # 拼接完整目录路径(基于MEDIA_ROOT)
    full_dir_path = os.path.join(settings.MEDIA_ROOT, dir_obj.directory_path)
    
    # 创建临时ZIP文件
    response = HttpResponse(content_type='application/zip')
    response['Content-Disposition'] = f'attachment; filename="{dir_obj.name}.zip"'
    
    with zipfile.ZipFile(response, 'w') as zipf:
        for root, dirs, files in os.walk(full_dir_path):
            for file in files:
                file_path = os.path.join(root, file)
                # 计算ZIP内的相对路径,避免把整个服务器路径加进去
                arcname = os.path.relpath(file_path, full_dir_path)
                zipf.write(file_path, arcname)
    
    return response

步骤4:配置URL

把视图加到URLconf里:

# urls.py
from django.urls import path
from .views import download_directory

urlpatterns = [
    # ... 其他URL
    path('download/directory/<int:dir_id>/', download_directory, name='download_directory'),
]

管理员只需要把目录放到MEDIA_ROOT下的对应路径,然后在Admin里添加一条记录,用户就能通过链接下载整个ZIP包了!

方案二:前端直接列出目录文件,支持单个下载

如果用户需要单独下载目录里的某个文件,结合Django的媒体文件配置,前端模板就能直接生成下载链接,几乎不用写额外视图。

步骤1:配置媒体文件访问

确保settings.py里已经配置了媒体文件的URL和路径:

# settings.py
MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
MEDIA_URL = '/media/'

然后在根URLconf里添加媒体文件的访问路由:

# root urls.py
from django.conf import settings
from django.conf.urls.static import static

urlpatterns = [
    # ... 其他URL
] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)

步骤2:写视图获取目录下的文件列表

# views.py
import os
from django.conf import settings
from django.shortcuts import render

def download_page(request, dir_path):
    full_dir_path = os.path.join(settings.MEDIA_ROOT, dir_path)
    # 获取目录下的所有文件(可根据需求调整是否包含子目录)
    files = [f for f in os.listdir(full_dir_path) if os.path.isfile(os.path.join(full_dir_path, f))]
    # 生成每个文件的下载URL
    file_urls = [f"{settings.MEDIA_URL}{dir_path}/{f}" for f in files]
    
    return render(request, 'download_page.html', {
        'dir_name': dir_path.split('/')[-1],
        'file_list': zip(files, file_urls)
    })

步骤3:前端模板渲染下载链接

<!-- templates/download_page.html -->
<h1>下载 {{ dir_name }}</h1>
<ul>
    {% for file, url in file_list %}
        <li><a href="{{ url }}" download="{{ file }}">{{ file }}</a></li>
    {% endfor %}
</ul>

这样用户就能在页面上看到目录里的所有文件,点击直接下载,完全不用像之前那样写单个文件的视图!

额外优化:用django-sendfile2简化单个文件下载

如果还是需要处理单个文件的下载,用django-sendfile2能省去手动打开文件的代码,安装后直接这样写:

# views.py
from django_sendfile import sendfile

def brochure(request):
    filename = 'kastom_profile.pdf'
    return sendfile(request, filename, attachment=True, attachment_filename='kastom_profile.pdf')

是不是比原来的代码简洁多了?

内容的提问来源于stack exchange,提问作者Dennis Gathagu

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.21 06:47:31