Django 图片上传与下载

写在前面

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

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

GPT-4 的决策在股市中进行量化投资

论文题目:Can Large Language Models Beat Wall Street? Unveiling the Potential of AI in Stock Selection 论文链接:https://arxiv.org/abs/2401.03737 博客地址:https://www.marketsense-ai.com/ 从本质上来说&#xff0c;股票选择是个价格发现机制&#xff0c;在股票投…

深入解析ESP32C3(2)- 存储类型和地址空间

ESP32C3芯片的存储资源 • 384 KB 的ROM&#xff1a;用于程序启动和内核功能调用 • 400 KB 片上SRAM&#xff1a;用于数据和指令存储&#xff0c;时钟频率可配置&#xff0c;最大160 MHz。400 KB SRAM 中&#xff0c;有16 KB 配置为cache 专用 • RTC 快速存储器&#xff1a;…

VC++中使用OpenCV进行形状和轮廓检测

VC中使用OpenCV进行形状和轮廓检测 在VC中使用OpenCV进行形状和轮廓检测&#xff0c;轮廓是形状分析以及物体检测和识别的有用工具。如下面的图像中Shapes.png中有三角形、矩形、正方形、圆形等&#xff0c;我们如何去区分不同的形状&#xff0c;并且根据轮廓进行检测呢&#…

初学python系列: pandas操作excel

媳妇工作中经常用到excel处理&#xff0c;想用python处理excel更高效&#xff0c;所以自学了python&#xff0c;觉得python比Java还是简单多了&#xff0c;没有变量类型声明&#xff0c;比Java也就多了元组&#xff0c;各种库很丰富。 需求是&#xff1a; 汇总两个excel中 列&…

【MySQL】一文总结MVCC多版本并发控制

目录 MVCC 介绍当前读和快照读当前读快照读 MVCC 原理解析隐式字段Undo Log版本链Read ViewRead View 可见性原则 RC 和 RR 下的 Read ViewRC 下的 Read ViewRR 下的 Read View小结RR 级别下能否防止幻读总结 MVCC 介绍 在当今高度并发的数据库环境中&#xff0c;有效的并发控…

系统架构设计师教程(十二)信息系统架构设计理论与实践

信息系统架构设计理论与实践 12.1 信息系统架构基本概念及发展12.1.1 信息系统架构的概述12.1.2 信息系统架构的发展12.1.3 信息系统架构的定义 12.2 信息系统架构12.2.1 架构风格12.2.2 信息系统架构分类12.2.3 信息系统架构的一般原理12.2.4 信息系统常用4种架构模型12.2.5 企…

flink结合Yarn进行部署

1. 什么是Yarn模式部署Flink 独立&#xff08;Standalone&#xff09;模式由 Flink 自身提供资源&#xff0c;无需其他框架&#xff0c;这种方式降低了和其他第三方资源框架的耦合性&#xff0c;独立性非常强。但我们知道&#xff0c;Flink 是大数据计算框架&#xff0c;不是资…

[娱乐]索尼电视安装Kodi

索尼电视不能直接apk安装kodi应用 android studio安装后附带 abd&#xff0c; 路径 C:\Users\[yourname]\AppuoData\Local\Android\Sdk\platform-tools\adb.exe安卓电视点击内部版本号&#xff0c;启用开发者模式 adb 连接索尼安卓电视&#xff0c;记得电视上运行调试 abi选…

Vue——计算属性

文章目录 计算属性computed 计算属性 vs methods 方法计算属性完整写法 综合案例&#xff1a;成绩案例 计算属性 概念&#xff1a;基于现有的数据&#xff0c;计算出来的新属性。依赖的数据变化&#xff0c;自动重新计算 语法: ①声明computed配置项中&#xff0c;一个计算属性…

stable diffuison的安装和使用

stable diffuison的安装和使用 简单介绍 Stable Diffusion是一个深度学习文本到图像的生成模型&#xff0c;它可以根据文本描述生成详细的图像。这个模型主要应用于文本生成图像的场景中&#xff0c;通过给定的文本提示词&#xff0c;模型会输出一张与提示词相匹配的图片。 S…

C++提高编程---模板---类模板

目录 一、类模板 1.模板 2.类模板的作用 3.语法 4.声明 二、类模板和函数模板的区别 三、类模板中成员函数的创建时机 四、类模板对象做函数参数 五、类模板与继承 六、类模板成员函数类外实现 七、类模板分文件编写 八、类模板与友元 九、类模板案例 一、类模板 …

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…

数据结构【DS】Ch8 排序

文章目录 插入排序选择排序归并&基数外部排序 插入排序 交换排序 选择排序 归并&基数 外部排序

电脑可以连接wifi,甚至可以qq聊天,但就是不能用浏览器上网,一直显示未检测出入户网线的解决方案

今天回到家&#xff0c;准备办公却发现电脑可以连接wifi&#xff0c;甚至可以qq聊天&#xff0c;但就是不能用浏览器上网&#xff0c;一直显示未检测出入户网线的解决方案&#xff0c;小白也可以看懂 以下有几种解决方案&#xff0c;不妨都试试&#xff0c;估计可以解决95%的相…

【C语言基础篇】结构控制(下)转向语句break、continue、goto、return

文章目录 一、break语句 1. break在 while 循环中 2. break在 for 循环中 3. break在 do…while 循环中 4. break在 switch 语句中 5. break 总结 二、continue语句 1. continue在 while 循环中 2. continue在 for 循环中 3. continue在 do...while 循环中 4. con…

PY调包侠——Collections高效库

一、【写在前面】 PY是一个调包侠语言&#xff0c;多学一个库可以提高计算速度。Collections提供了各种数据类型和集合工具&#xff0c;可以很方便的处理各种数据结构。如果您有刷力扣的习惯&#xff0c;可以经常看到Collections和itertools的身影&#xff0c;经常用这两个可以…

【数据结构】二叉树相关oj题(一)

目录 1、二叉树的构建及遍历 1.1、题目介绍 1.2、解题思路 1.3、代码描述 1.4、完整代码 2、二叉树的层次遍历 2.1、题目介绍 2.2、解题思路 2.3、代码描述 2.4、完整代码 1、二叉树的构建及遍历 1.1、题目介绍 原题链接&#xff1a;KY11 二叉树构建及遍历_牛客题霸…

ElasticSearch 7.x现网运行问题汇集1

问题描述&#xff1a; 现网ElasticSearch health状态变为red&#xff0c;有分片无法assign。如下摘录explain的结果部分&#xff1a; "note": "No shard was specified in the explain API request, so this response explains a randomly chosen unassigned s…

docker 部署 sentinel

docker 部署 sentinel 环境安装 拉取镜像 目前稳定的版本是1.8.0 docker pull bladex/sentinel-dashboard:1.8.0启动服务 docker run --name sentinel -p 8858:8858 -td bladex/sentinel-dashboard:1.8.0登录 登录的时候账号和密码都是sentinel

openGauss学习笔记-203 openGauss 数据库运维-常见故障定位案例-修改索引时只调用索引名提示索引不存在

文章目录 openGauss学习笔记-203 openGauss 数据库运维-常见故障定位案例-修改索引时只调用索引名提示索引不存在203.1 修改索引时只调用索引名提示索引不存在203.1.1 问题现象203.1.2 原因分析203.1.3 处理办法 openGauss学习笔记-203 openGauss 数据库运维-常见故障定位案例-…