Django 图片上传与下载

news2025/1/11 16:54:12

写在前面

在Web开发中,文件上传和下载是常见的功能之一。

Django 是一位魔法师🪄,为我们提供了 FileField ImageField 等神奇得字段类型,以及相应的视图和模板标签,使得处理文件变得十分便捷。本文以图片上传作为示例,向各位小伙伴展示如何使用Django框架构建一个简单的图片上传与下载功能的项目。🌝

完整代码见:https://github.com/MaitreChen/django-upload-download-demo

接下来,就由笔者手把手带你如何和在Django的舞台上演绎一场简单而精彩的图片上传与下载的戏码!🎉

准备工作

创建django项目,并创建应用程序:

django-admin startproject upload_download_demo
python manage.py startapp demo

setting.py添加应用程序:

INSTALLED_APPS = [
    xxx
    'demo',
]

在django项目目录创建media文件夹,并在setting.py中进行配置路径:

import os

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

需要说明的是,在Django项目使用文件上传功能时,MEDIA路径是用来存储用户上传的媒体文件(例如图片、文档等)的位置,这是Django处理媒体文件的标准配置方式。

步骤一:定义模型类

模型(Model)是Django中的一个组件,用于定义数据的结构和规则,以便存储在数据库中。模型描述了数据的种类、字段类型、约束条件等,它充当着数据库表的蓝图,确保数据的一致性和完整性。

from django.db import models
from os.path import basename


class Record(models.Model):
    name = models.CharField(max_length=100)
    image = models.ImageField(upload_to='images/') # 指定图片文件存储在media/images文件夹内

    def get_image_name(self):
        return basename(self.image.name)

需要说明的是,这里定义get_image_name()函数是为了便于获取图片文件名,以在前端模板显示,非常好用~~

然后做一下数据库迁移:

python manage.py makemigrations
python manage.py migrate
  • 第一条命令会生成数据库迁移文件,包含了关于模型变更的描述,所以模型如果添加或删除字段的时候就要做迁移;
  • 第二条命令会应用变更,将模型映射到数据库表。

步骤二:定义表单

表单的定义是为了在Web应用中收集用户输入的数据,然后将其传递给后端处理,以创建、更新或查询数据库中的相应记录。

举个栗子🌰,表单就像是网页中的小秘书,它的任务是接收用户的各种奇思妙想,然后把这些信息悄悄地传递给后端大Boss。这样,后端Boss就能够以一种魔法般的方式创造、更新或者找到数据库中的相应“秘密档案”了!

from django import forms
from .models import Record


class RecordForm(forms.ModelForm):
    class Meta:
        model = Record
        fields = ['image']
  • RecordForm继承自forms.ModelForm,表示这是一个基于模型的表单;
  • 在RecordForm内部,有一个内嵌的Meta类,用于配置一些表单的元数据
  • fields = ['image'] 指定了在表单中包含哪些字段,由于我们在上传时只需要选择图片,所以我们添加一个image字段即可,如果要输入其他字段,比如titile,那这里也应该相应添加。

步骤三:构建视图函数

让我们编写一个能够在前端舞台上展示图像的视图,笔者为小伙伴们做了逐行解释(好贴心!)

from django.shortcuts import render, redirect
from django.http import HttpResponse
from django.conf import settings
from urllib.parse import quote
import os
from .forms import RecordForm  # 导入图片上传表单
from .models import Record  # 导入图片上传模型类


# 图片上传
def upload_image(request):
    # 检查表单是否提交
    if request.method == 'POST':
        # 使用提交的数据创建一个表单实例
        form = RecordForm(request.POST, request.FILES)

        # 检查表单数据是否有效
        if form.is_valid():
            # 将表单数据保存到数据库
            form.save()

            # 成功提交后重定向到相同页面
            return redirect('upload_image')
    else:
        # 如果是 GET 请求,创建一个空表单
        form = RecordForm()

    # 从数据库中检索所有记录
    records = Record.objects.all()

    # 使用表单和记录渲染模板,这样我们可以在前台获取records的属性值并显示
    return render(request, 'upload_image.html', {'form': form, 'records': records})


# 图片下载
def download_image(request, filename):
    # 构建文件路径
    file_path = os.path.join(settings.MEDIA_ROOT, 'images', filename)

    # 获取文件扩展名
    _, file_extension = os.path.splitext(filename.lower())

    # 根据文件扩展名确定内容类型,由于我们下载的是图片数据,所以添加常见的格式
    content_type_mapping = {
        '.jpg': 'image/jpeg',
        '.jpeg': 'image/jpeg',
        '.png': 'image/png',
    }

    # 如果找不到扩展名,默认使用 'application/octet-stream'
    content_type = content_type_mapping.get(file_extension, 'application/octet-stream')

    # 读取文件内容并创建响应对象
    with open(file_path, 'rb') as file:
        response = HttpResponse(file.read(), content_type=content_type)

    # 设置 Content-Disposition 修改文件名,否则下载时浏览器会给你默认名字,比如"下载.jpg"
    response['Content-Disposition'] = f'attachment; filename={quote(filename)}'

    return response

步骤四:构建模板

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Upload and Download</title>
</head>
<body>

<div id="content">
    <form method="post" enctype="multipart/form-data">
        {% csrf_token %}
        {{ form.as_p }}
        <button type="submit">Upload Image</button>
    </form>

    <table>
        <thead>
        <tr>
            <th>Number</th>
            <th>Image Name</th>
            <th>Action</th>
        </tr>
        </thead>
        <tbody>
        {% for record in records %}
            <tr>
                <td>{{ forloop.counter }}</td>
                <td>{{ record.get_image_name }}</td>
                <td>
                    <a href="{% url 'download_image' filename=record.get_image_name %}" download>
                        Download
                    </a>
            </tr>
        {% endfor %}
        </tbody>
    </table>
</div>

</body>
</html>

第一部分,form标签中的内容表示图片上传表单。

  • method="post" 表示使用 POST 方法提交表单;
  • enctype="multipart/form-data" 表示支持文件上传;
  • {% csrf_token %} 添加了一个 CSRF 令牌,用于防止跨站请求伪造攻击;
  • {{ form.as_p }} 将表单的字段以段落形式呈现,使其更易于阅读;
  • button是提交按钮,用于触发上传操作;

第二部分,这里笔者使用了table标签,以表格形式呈现在前台。

  • 使用table表格,列出了每个图片的序号、图片名称和一个用于下载的链接;
  • 使用 {% for record in records %} 迭代遍历所有记录;
  • {% forloop.counter %} 提供了当前迭代的计数,不是必要的,只是为了前台为每一条记录编个号而已~
  • 下载链接使用 {% url 'download_image' filename=record.get_image_name %} 来构建下载图片的URL,download 属性用于提示浏览器下载文件而不是直接打开!
  • 另外,笔者只是为了带大家实现基本的功能,就不设置花里胡哨的style了~~

步骤五:配置URL

在应用程序app中添加文件上传与下载的url:

#demo/urls.py

from django.urls import path
from .views import upload_image, download_image

urlpatterns = [
    path('upload/', upload_image, name='upload_image'),
    path('download/<str:filename>/', download_image, name='download_image'),
]

我们解释一下download部分:

  • 'download/<str:filename>/': 代表实际的URL模式。它包含了一个变量 <str:filename>,表示在这个位置匹配一个字符串,并将其作为名为 filename 的参数传递给视图函数。例如,如果URL为 download/my_image.jpg/,那么 my_image.jpg 将被传递给视图函数。
  • name='download_image': 为这个URL模式起个小名,以便在Django中的其他地方引用。通过这个名字,我们可以在模板或其他地方使用 {% url 'download_image' filename=record.get_image_name %} 来生成对应的URL。

不要忘了在django项目添加app的url:

# upload_download_demo/urls.py

from django.contrib import admin
from django.urls import path, include

urlpatterns = [
    path("admin/", admin.site.urls),
    path('', include('demo.urls')),
]

终极测试

启动开发服务器的命令:

python manage.py runserver

浏览器访问:http://127.0.0.1:8000/upload

在Django的奇妙世界,我们每个人都是一位魔法师,通过巧妙的咒语让用户轻松上传魔法图谱,然后在魔法图书馆里畅游,尽情下载这些奇幻之书!🧙✨

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1401847.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

HTML CSS 发光字头特效

效果展示&#xff1a; 代码&#xff1a; <html><head> </head><style>*{margin: 0;padding: 0;}body {text-align: center;}h1{/* border: 3px solid rgb(201, 201, 201); */margin-bottom: 20px;}.hcqFont {position: relative;letter-spacing: 0.07…

深度解析Python关键字:掌握核心语法的基石(新版本35+4)

目录 关键字 keyword 关键字列表 kwlist softkwlist 关键字分类 数据类型 True、False None 运算类型 and、or、not in is 模块导入 import 辅助关键字 from、as 上下文管理 with 占位语句 pass 流程控制 if、elif、else for while break、continue…

【C语言】动态内存函数介绍

目录 1.malloc和free 2.calloc 3.realloc 1.malloc和free C语言提供了一个动态内存开辟的函数malloc&#xff1a; void* malloc(size_t size); 这个函数向内存申请一块连续可用的空间&#xff0c;并返回指向这块空间的指针。 ✔如果开辟成功&#xff0c;则返回一个指向开…

数据分析实战:城市房价分析

流程图&#xff1a; 1.读数据表 首先&#xff0c;读取数据集。 CRIMZNINDUSCHASNOXRMAGEDISRADTAXPTRATIOBLSTATtarget0.00632182.3100.5386.57565.24.09129615.3396.94.98240.0273107.0700.4696.42178.94.9671224217.8396.99.1421.60.0272907.0700.4697.18561.14.9671224217…

Python-import hook机制原理与使用

背景 钩子函数&#xff08;hook function&#xff09;&#xff0c;可以理解是一个挂钩&#xff0c;作用是有需要的时候挂一个东西上去。具体的解释是&#xff1a;钩子函数是把我们自己实现的hook函数在某一时刻挂接到目标挂载点上。 在 Python 众多特性中&#xff0c;有一个特…

【设计模式】代理模式的实现方式与使用场景

1. 概述 代理模式是一种结构型设计模式&#xff0c;它通过创建一个代理对象来控制对另一个对象的访问&#xff0c;代理对象在客户端和目标对象之间充当了中介的角色&#xff0c;客户端不再直接访问目标对象&#xff0c;而是通过代理对象间接访问目标对象。 那在中间加一层代理…

大模型学习与实践笔记(十一)

一、使用OpenCompass 对模型进行测评 1.环境安装&#xff1a; git clone https://github.com/open-compass/opencompass cd opencompass pip install -e . 当github超时无法访问时&#xff0c;可以在原命令基础上加上地址&#xff1a; https://mirror.ghproxy.com git clon…

UG制图-创建图纸的多种方法

1、2D&#xff1a;创建独立2D图纸&#xff0c;不引用任何3D模型 在UG软件中选择新建&#xff0c;或者快捷键ctrl N&#xff0c;进入新建命令&#xff0c;然后点击图纸&#xff0c;在关系中选择独立的部件&#xff0c;就创建了一个独立的图纸&#xff0c;我们可以在装配中添加…

java eazyexcel 实现excel的动态多级联动下拉列表(1)使用名称管理器+INDIRECT函数

原理 将数据源放到一个新建的隐藏的sheet中将选项的子选项的对应字典设置到名称管理器中&#xff08;名称是当前选项的内容&#xff0c;值是他对应的子菜单的单元格范围&#xff0c;在1里面的sheet中&#xff09;子菜单的数据根据INDIRECT函数去左边那个单元格获取内容&#x…

KMP 算法详解(C++ Version)

KMP 算法详解&#xff08;C Version&#xff09; 简述字符串匹配问题Brute-Force 算法Brute-Force 算法的改进思路跳过不可能成功的字符串比较next 数组利用 next 数组进行匹配快速求 next 数组 简述 KMP 算法是一种字符串匹配算法&#xff0c;可以在 O(nm) 的时间复杂度内实现…

ZYNQ程序固化

文章目录 一、简介二、固化操作2.1 生成固化文件2.2 固化到SD卡2.3 固化到Flash 参考 将程序存储在非易失性存储器中&#xff0c;在上电或者复位时让程序自动加载运行。 这个过程需要启动引导程序( Boot Loader)参与&#xff0c;Boot Loader会加载FPGA配置文件&#xff0c;以及…

读元宇宙改变一切笔记12_元宇宙+

1. 元宇宙的价值 1.1. 元宇宙的价值&#xff0c;将“超过”物理世界 1.2. 移动互联网时代不是突然降临的 1.2.1. 我们可以确定一项特定的技术是何时被创造、测试或部署的&#xff0c;但不能确定一个时代何时开始或何时结束 1.2.2. 转型是一个迭代的过程&#xff0c;在这个过…

web架构师编辑器内容-完成属性设置的优化

对于业务组件来说&#xff0c;其属性是有很多的&#xff0c;如果把所有属性都平铺在页面上&#xff0c;就会非常长&#xff0c;而且想要更改其中的某些属性&#xff0c;可能需要向下滚动很久才能找到&#xff0c;对于UI的交互不是很友好&#xff0c;需要对属性的不同特性进行分…

彩色图像处理之彩色图像直方图处理的python实现——数字图像处理

彩色图像的直方图处理是一种重要的图像处理技术&#xff0c;用于改善图像的视觉效果&#xff0c;增强图像的对比度&#xff0c;或为后续的图像处理任务&#xff08;如图像分割、特征提取&#xff09;做准备。彩色图像通常由红色&#xff08;R&#xff09;、绿色&#xff08;G&a…

2023年12月 Scratch 图形化(一级)真题解析#中国电子学会#全国青少年软件编程等级考试

Scratch图形化等级考试(1~4级)全部真题・点这里 一、单选题(共25题,每题2分,共50分) 第1题 观察下列每个圆形中的四个数,找出规律,在括号里填上适当的数?( ) A:9 B:17 C:21 D:5 答案:C 左上角的数=下面两个数的和+右上角的数

【UEFI基础】EDK网络框架(UDP4)

UDP4 UDP4协议说明 UDP的全称是User Datagram Protocol&#xff0c;它不提供复杂的控制机制&#xff0c;仅利用IP提供面向无连接的通信服务。它将上层应用程序发来的数据在收到的那一刻&#xff0c;立即按照原样发送到网络。 UDP报文格式&#xff1a; 各个参数说明如下&…

Tomcat Notes: Web Security

This is a personal study notes of Apache Tomcat. Below are main reference material. - YouTube Apache Tomcat Full Tutorial&#xff0c;owed by Alpha Brains Courses. https://www.youtube.com/watch?vrElJIPRw5iM&t801s 1、Overview2、Two Levels Of Web Securi…

跨部门算法迭代需求,从提出到上线的全流程实践

文章目录 引言需求评审技术方案评审模块开发系统联调QA测试产品验收经验教训 引言 最近工作中有一个算法迭代的需求&#xff0c;我在其中作为技术侧负责人&#xff08;技术主R&#xff09;推动需求完成上线。 需求涉及多个部门&#xff0c;前后耗时接近1个月。 我第一次在这…

transdata笔记:手机数据处理

1 mobile_stay_duration 每个停留点白天和夜间的持续时间 transbigdata.mobile_stay_duration(staydata, col[stime, etime], start_hour8, end_hour20) 1.1 主要参数 staydata停留数据&#xff08;每一行是一条数据&#xff09;col 列名&#xff0c;顺序为[‘starttime’,…

Istio

1、Istio介绍 Istio 是由 Google、IBM 和 Lyft 开源的微服务管理、保护和监控框架。 官网&#xff1a;https://istio.io/latest/zh/ 官方文档&#xff1a;https://istio.io/docs/ 中文官方文档&#xff1a;https://istio.io/zh/docs Github地址&#xff1a;https://github.com…