Django 图片上传与下载

写在前面

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

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

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

Django 图片上传与下载_第1张图片

接下来,就由笔者手把手带你如何和在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

步骤四:构建模板




    
    
    Upload and Download



{% csrf_token %} {{ form.as_p }}
{% for record in records %} {% endfor %}
Number Image Name Action
{{ forloop.counter }} {{ record.get_image_name }} Download

第一部分,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//', download_image, name='download_image'),
]

我们解释一下download部分:

  • 'download//': 代表实际的URL模式。它包含了一个变量 ,表示在这个位置匹配一个字符串,并将其作为名为 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的奇妙世界,我们每个人都是一位魔法师,通过巧妙的咒语让用户轻松上传魔法图谱,然后在魔法图书馆里畅游,尽情下载这些奇幻之书!✨

你可能感兴趣的:(Django,学习笔记,django,python,后端)