Python+django实现文件下载

下面是关于Python+django实现文件下载的完整攻略以及两条示例说明。

什么是Django?

Django是一个Python Web框架,采用了MVC的软件架构模式,是一个全功能的高级Web框架。Django的官方网站是djangoproject.com

Django实现文件下载的方法

在Django中,可以通过编写视图函数实现文件的下载。

示例1:基础实现

1. 在urls.py中添加路由

首先,在项目的urls.py文件中添加文件下载的路由。假设我们要下载的文件名为 test.zip,我们可以将这个路由设置为/downloads/test:

from django.urls import path
from . import views
urlpatterns = [
    # ... 其他路由 ...
    path('downloads/<str:filename>', views.download_file, name='download_file'),
]

2. 编写视图函数

接下来,我们需要定义视图函数来处理/downloads/这个路由。以下是一个简单的示例视图函数:

import os
from django.http import HttpResponse

def download_file(request, filename):
    # 获取文件路径
    file_path = os.path.join(settings.BASE_DIR, 'downloads', filename)

    # 判断文件是否存在
    if os.path.exists(file_path):
        # 打开文件
        with open(file_path, 'rb') as f:
            # 构造HttpResponse对象,并设置文件头
            response = HttpResponse(f.read())
            response['Content-Type'] = 'application/octet-stream'
            response['Content-Disposition'] = 'attachment;filename=' + filename

            return response
    else:
        return HttpResponse('File not found')

该函数从request对象中获取了文件名参数filename,然后通过os模块拼接出了文件的绝对路径。如果文件存在,函数就打开文件并构造HttpResponse对象,并设置Content-Type和Content-Disposition这两个文件头,最后将HttpResponse对象返回。如果文件不存在,函数会返回一个字符串“File not found”。

3. 将文件存储到项目目录中

在以上的视图函数中,我们通过os模块拼接出了文件的绝对路径。在这个例子中,我们将文件存储在了项目目录的downloads文件夹下:

myproject/
  downloads/
    test.zip
  myproject/
    settings.py
    urls.py
    views.py
    ...

示例2:通过模型动态生成文件并下载

如果需要动态生成文件并下载,我们可以在视图函数中通过Python生成文件,然后以文件流的方式向HttpResponse对象中写入。

1. 创建模型

首先,我们需要在models.py中创建一个模型,用于保存需要生成的数据。例如,我们可以创建一个叫做FileData的模型:

from django.db import models
from django.utils import timezone

class FileData(models.Model):
    filename = models.CharField(max_length=255, unique=True)
    data = models.TextField()
    created_date = models.DateTimeField(default=timezone.now)

2. 创建生成文件的函数

然后,我们需要创建一个生成文件的函数。以生成CSV文件为例:

import csv

def generate_csv(filedata):
    # 将data字段中的字符串解析为二维列表
    data = list(csv.reader(filedata.data.splitlines()))

    # 打开文件
    fp = open(filedata.filename, 'w', newline='', encoding='utf-8')

    # 写入文件内容
    writer = csv.writer(fp)
    for row in data:
        writer.writerow(row)

    # 关闭文件
    fp.close()

该函数接收一个FileData对象作为参数,并将该对象的data字段中的字符串解析为二维列表,然后通过csv模块将该二维列表写入到文件中。

3. 编写视图函数

接下来,我们需要定义视图函数来处理/downloads//csv这个路由。以下是一个简单的示例视图函数:

import os
import csv
from django.http import HttpResponse
from django.shortcuts import get_object_or_404
from .models import FileData

def download_csv(request, pk):
    # 获取要下载的FileData对象
    filedata = get_object_or_404(FileData, pk=pk)

    # 生成CSV文件并获取文件路径
    generate_csv(filedata)
    file_path = filedata.filename

    # 打开文件
    with open(file_path, 'rb') as f:
        # 构造HttpResponse对象并设置文件头
        response = HttpResponse(f.read())
        response['Content-Type'] = 'application/octet-stream'
        response['Content-Disposition'] = 'attachment;filename=' + filedata.filename

        # 返回HttpResponse对象
        return response

该函数接收一个FileData的主键作为参数pk,并通过get_object_or_404函数获取到对应的FileData对象。然后,该函数通过generate_csv函数生成CSV文件,并在HttpResponse对象中设置Content-Type和Content-Disposition这两个文件头,最后将HttpResponse对象返回。

4. 将模型保存到数据库

最后,我们需要在视图函数中创建一个FileData对象,将其保存到数据库中,并且将其主键作为下载路由的参数。例如:

from django.urls import path
from . import views
urlpatterns = [
    # ... 其他路由 ...
    path('downloads/csv/<int:pk>/', views.download_csv, name='download_csv'),
]

然后在views.py中创建一个视图函数,用来生成FileData对象并保存到数据库:

def save_csv(request):
    # 生成CSV数据
    data = [
        ['Name', 'Age', 'Email'],
        ['Jack', '24', 'jack@example.com'],
        ['Mary', '30', 'mary@example.com'],
        ['Tom', '18', 'tom@example.com'],
    ]

    # 创建FileData对象并保存到数据库
    filedata = FileData(filename='test.csv', data=csv.writer(data).getvalue())
    filedata.save()

    # 重定向到下载视图
    return redirect('download_csv', pk=filedata.pk)

该函数生成CSV数据,然后创建FileData对象,并将其保存到数据库中。最后,该函数通过redirect函数将页面重定向到/download/csv//这个路由,其中pk参数用FileData对象的主键来替代。

常见问题

Q1:如果被下载的文件很大,会不会占用过多的内存?

如果被下载的文件非常大,那么将其读入内存可能会导致内存溢出。为了避免这个问题,我们可以对文件进行分块读取。例如,以下是一个读取文件并以分块的方式返回HttpResponse对象的示例代码:

with open(file_path, 'rb') as f:
    response = StreamingHttpResponse(iter(lambda: f.read(4096), b''))
    response['Content-Type'] = 'application/octet-stream'
    response['Content-Disposition'] = 'attachment;filename=' + filename
    return response

这里的iter函数会将文件按照每次读取4096个字节的方式进行分块,然后将每一块返回给HttpResponse对象。

Q2:如何在模板中添加下载链接?

在模板中,我们可以使用url函数来生成下载链接。例如,以下是一个在模板中生成下载链接并添加到表格中的示例代码:

<tr>
    <td>{{ filedata.filename }}</td>
    <td><a href="{% url 'download_file' filename=filedata.filename %}">下载</a></td>
</tr>

该代码中的{% url 'download_file' filename=filedata.filename %}会生成一个下载链接,并将文件名作为参数传递给视图函数download_file。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:Python+django实现文件下载 - Python技术站

(0)
上一篇 2023年5月16日
下一篇 2023年5月16日

相关文章

  • django自定义标签错误 ‘my_tag’ is not a registered tag library.

    解决办法: 在settings里的 加上红色的部分,my_tag为自定义的标签函数 后面的为其地址  TEMPLATES = [ { ‘BACKEND’: ‘django.template.backends.django.DjangoTemplates’, ‘DIRS’: [os.path.join(BASE_DIR, ‘templates’)] , ‘AP…

    Django 2023年4月11日
    00
  • Django命名空间app_name和namespace

    在多个app之间,有可能产生同名的url,这个时候避免反转url的时候混淆,可以使用应用命名空间做区分。应用命名空间使用。在应用url中定义 app_name; 一个app,可以创建多个url映射到一个app中,所以就会产生一个问题,在做反转的时候,如果不使用命名空间,就会混淆,为了避免这个问题。我们可以使用实例命名空间。在include函数中添加names…

    Django 2023年4月11日
    00
  • 虚拟环境下搭建一个Django项目

    下面是虚拟环境下搭建Django项目的攻略: 安装虚拟环境 在终端中输入以下命令来安装虚拟环境: $ pip install virtualenv 创建虚拟环境 在终端中输入以下命令来创建虚拟环境: $ virtualenv myenv 其中myenv是你要创建的虚拟环境的名字。 激活虚拟环境 在终端中输入以下命令来激活虚拟环境: $ source myen…

    Django 2023年5月16日
    00
  • Django 模型类(models.py)的定义详解

    我们一起来详细讲解下“Django 模型类(models.py)的定义详解”。 什么是Django模型类 Django 模型类是用来在数据库中创建表格的一个抽象,也是Django 框架中的一项非常重要的功能。模型类/数据模型是指定义方法中包含了存储数据的结构,将数据存储在数据库中,可以理解为Django的“数据表”。 通过Django模型类,可以通过定义属性…

    Django 2023年5月16日
    00
  • Django中static(静态)文件详解以及{% static %}标签的使用

    在一个网页中,不仅仅只有一个html骨架,还需要css样式文件,js执行文件以及一些图片等。因此在DTL中加载静态文件是一个必须要解决的问题。在DTL中,使用static标签来加载静态文件。要使用static标签,首先需要{% load static %}。 加载静态文件的步骤如下: 首先确保django.contrib.staticfiles已经添加到se…

    Django 2023年4月13日
    00
  • GraphQL在Django中的使用教程

    下面是关于“GraphQL在Django中的使用教程”的完整攻略,包含两条示例说明: 1. 介绍 GraphQL是一种用于API开发的查询语言和运行时。它被归类为替代REST的API解决方案之一。它具有强大的查询语言、类型安全、自动化API文档生成、动态查询、精确响应、递归查询等优点。同时,GraphQL也可以与Django集成,使用GraphQL可以在Dj…

    Django 2023年5月15日
    00
  • django session源码剖析

    django之所以能实现登陆认证,依靠的是一个叫sessionid的东西,该id记录了你的认证信息,如果你不喜欢这个名称,你也可以通过修改settings配置SESSION_COOKIE_NAME settings解说之session # Cache to store session data if using the cache session backe…

    Django 2023年4月11日
    00
  • Linux部署Django:报错 nohup: ignoring input and appending output to ‘nohup.out’

    一、部署 Django 到远程 Linux 服务器 利用 xshell 通过 ssh 连接到 Linux服务器,常规的启动命令是 python3 manage.py runserver 0.0.0.0:80 但是,关闭 xshell 后,就访问不了 Django 了。 这时候需要使用 nohup 命令启动(概念:如果你正在运行一个进程,而且你觉得在退出帐户时…

    Django 2023年4月10日
    00
合作推广
合作推广
分享本页
返回顶部