174.Django中文件上传和下载

1. 文件上传和下载环境搭建

  1. 创建django项目和子应用
  2. urls中包含子应用,在子应用中创建urls.py
  3. 配置数据库sqlite3(默认就是,无需配置)
  4. 配置settings,上传文件目录
  5. 编写模型代码(下面给出)
  6. 模型的预迁移和迁移
  7. Nacicat创建数据库,然后查看表
  8. 根目录下创建文件夹media
  9. 可以翻阅本专栏,前面都有介绍

models.py

from django.db import models

# Create your models here.

# 上传文件
class UploadFileImg(models.Model):
    # 上传普通文件
    file = models.FileField(upload_to="files/")
    # 上传图片
    img = models.ImageField(upload_to='imgs/')
    remark = models.CharField(max_length=100)

在这里插入图片描述
settings

ROOT_URLCONF = 'file_study.urls'
import os
TEMPLATES = [
    {
        'BACKEND': 'django.template.backends.django.DjangoTemplates',
        'DIRS': [os.path.join(BASE_DIR,'templates')],
        'APP_DIRS': True,
        'OPTIONS': {
            'context_processors': [
                'django.template.context_processors.debug',
                'django.template.context_processors.request',
                'django.contrib.auth.context_processors.auth',
                'django.contrib.messages.context_processors.messages',
            ],
        },
    },
]
# 配置上传文件路径
MEDIA_URL = '/media/'
MEDIA_ROOT = os.path.join(BASE_DIR,'media')

根urls

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

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

# 上传文件配置
from django.conf import settings
from django.conf.urls.static import static

if settings.DEBUG:
    urlpatterns += static(settings.MEDIA_URL, document_root = settings.MEDIA_ROOT)

2. 文件上传admin管理

配置admin.py

from django.contrib import admin
from file_app.models import UploadFileImg
# Register your models here.

admin.site.register(UploadFileImg)

创建管理用户
在这里插入图片描述
访问admin
在这里插入图片描述
测试
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

3. 前端显示和下载

views

from django.shortcuts import render
from file_app.models import UploadFileImg
# Create your views here.
# 根据pk获取UploadFileImg对象
def file_admin(request,pk):
    upload_file_img = UploadFileImg.objects.get(pk=pk)
    return render(request,'file_app/file_admin.html', {'upload_file_img':upload_file_img})


templates

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>admin管理文件上传</title>
</head>
<body>
    <ul>
        <li>备注:{{ upload_file_img.remark }}</li>
        <li>图片名称:{{ upload_file_img.img.name }}</li>
        <li><img src="{{ upload_file_img.img.url }}"></img>></li>
        <!-- 点击链接进行下载 -->
        <li><a href="{{ upload_file_img.file.url }}">{{ upload_file_img.file.name }}</a></li>
    </ul>
</body>
</html>

效果展示
在这里插入图片描述

4.上传文件高阶功能——重复文件名保存处理

4.1 问题概述

当我们保存文件时候,多个同样名称的文件进行保存时,会出现异常,这里,我们将使用时间戳的方式区分文件。
FileField和ImageField类的属性upload_to,除了可以填写字符串,例如:‘imgs/’,还可以指定一个自定义函数,用于根据文件模型实例以及文件信息做一些额外操作,譬如:单独设置目录

4.2 操作流程

models模型

from django.db import models
import time
import os
# Create your models here.
def upload_to_func(instance, filename):
    '''
    上传图片路径
    :param instance:模型对象实例
    :param filename:文件名
    :return: 保存的路径
    '''
    try:
        #filename 是aa.txt
        index = filename.index('.')
        # aa
        pre = filename[:index]
        # .txt
        sub = filename[index:]
    except:
        # 文件名直接是 aa
        pre = filename
        sub = ''
    # aa_10位时间戳数字.txt
    filename = f'{pre}_{int(time.time())}{sub}'
    return os.path.join(instance.typ,filename)


class UploadFileImgAdvance(models.Model):
    typ = models.CharField(max_length=10, null=True)
    file = models.FileField(upload_to=upload_to_func)
    img = models.ImageField(upload_to=upload_to_func)

迁移数据库
创建admin对象

from django.contrib import admin
from file_app.models import UploadFileImg,UploadFileImgAdvance
# Register your models here.

admin.site.register(UploadFileImg)
admin.site.register(UploadFileImgAdvance)

登录/admin添加文件
在这里插入图片描述

创建视图类,前端显示和下载文件

from django.shortcuts import render
from file_app.models import UploadFileImg,UploadFileImgAdvance
from django.http import Http404
# Create your views here.
def file_advance(request,pk):
    try:
        uploadFileImg = UploadFileImgAdvance.objects.get(pk=pk)
        return render(request, 'file_app/file_admin_adv.html', {'uploadFileImg': uploadFileImg})
    except:
        raise Http404

templates

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <title>admin管理的文件显示</title>
</head>

<body>
    <ul>
        <li>
            类型:{{ uploadFileImg.typ }}
        </li>
        <li>
            图片名:{{uploadFileImg.img.name }}
        </li>
        <li>
            <img src="{{uploadFileImg.img.url }}">
        </li>
        <li>
            <a href="{{uploadFileImg.file.url }}">{{uploadFileImg.file.name }}</a>
        </li>
    </ul>
</body>

</html>

在这里插入图片描述

5.文件上传自定义管理

5.1 概述

不使用admin后台管理上传文件,使用自己渲染的页面进行上传

5.2 操作流程

创建模型,迁移模型

from django.db import models
import time
import os
def upload_to_func(instance, filename):
    '''
    上传图片路径
    :param instance:模型对象实例
    :param filename:文件名
    :return: 保存的路径
    '''
    try:
        #filename 是aa.txt
        index = filename.index('.')
        # aa
        pre = filename[:index]
        # .txt
        sub = filename[index:]
    except:
        # 文件名直接是 aa
        pre = filename
        sub = ''
    # aa_10位时间戳数字.txt
    filename = f'{pre}_{int(time.time())}{sub}'
    return os.path.join(instance.typ,filename)
class UploadFileImgDIY(models.Model):
    typ = models.CharField(max_length=10, null=False)
    file = models.FileField(upload_to=upload_to_func)
    img = models.ImageField(upload_to=upload_to_func)

views

from django.shortcuts import render
from file_app.models import UploadFileImg,UploadFileImgAdvance,UploadFileImgDIY
from django.http import Http404, HttpResponse
def file_diy(request):
    if request.method == 'POST':
        # 获取表单中的数据
        typ = request.POST.get('typ')
        img = request.FILES.get('img')
        file = request.FILES.get('file')
        upload_file_diy =  UploadFileImgDIY.objects.create(
            typ = typ,
            img = img,
            file = file
        )
        return HttpResponse(f'文件上传成功,id:{upload_file_diy.pk}')
    else:
        return render(request, "file_app/file_diy.html")

templates

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>自定义管理文件</title>
</head>
<body>
    <!-- 文件上传固定enctype -->
    <!-- form表单按钮执行方式,跳转到file_zidingyi:file_diy执行post -->
    <form action="{% url 'file_zidingyi:file_diy' %}" method="post" enctype="multipart/form-data">
        <!-- 文件上传表单时必须添加token,否则存在异常 -->
        {% csrf_token %}
        文件路径:<input type="text" name="typ"><br>
        图片:<input type="file" name="img"> <br>
        文件: <input type="file" name="file"> <br>
        <input type="submit" name="上传">
    </form>
</body>
</html>

效果展示
在这里插入图片描述

在这里插入图片描述

6.自定义文件下载

6.1 概述

在3和4中,我们使用html页面中的a标签进行文件下载,我们这里将在Django中使用StreamingHttpRespose实现自定义下载。
首先,应该创建视图函数,获取全部的页面,然后再创建视图函数进行下载的操作

6.2 操作流程

views

from django.shortcuts import render
from file_app.models import UploadFileImg,UploadFileImgAdvance,UploadFileImgDIY
from django.http import Http404, HttpResponse, StreamingHttpResponse
def file_diy_list(request):
    # 查询所有上传的文件
    file_diy_list = UploadFileImgDIY.objects.all()
    return render(request, "file_app/file_diy_list.html", {"file_diy_list":file_diy_list})
def file_diy_download(request):
    # 获取 记录id
    id = request.GET.get('id')
    # 得到模型实例对象
    upload_file_img_diy = UploadFileImgDIY.objects.get(pk = id)
    # 得到模型的FileField属性,获取文件的相对路径
    file = upload_file_img_diy.file
    # print("file:",file)
    # 得到FileField类的file属性,是一个文件对象, 获取到文件存放的绝对路径
    file_diy = file.file
    # print("file_diy:",file_diy)
    # 通过StreamingHttpResponse进行文件下载,传入的参数为文件的字节内容
    response = StreamingHttpResponse(file_diy.read())
    # 通过分割,将diy/test1_123451.csv获取到test1_123451.csv
    name = file.name.split('/')[-1]
    # 附件模式
    # 要进行编码和解码,以为http协议规定,响应头的编码格式必须是ISO-8859-1
    response['Content-Disposition'] = 'attachment;filename=' + name.encode('utf-8').decode('ISO-8859-1')
    return response

templates

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>自定义文件下载</title>
</head>
<body>
    <ul>
        {% for file in file_diy_list %}
        <li>
            id:{file.id}
            typ:{file.typ}
            <!-- 跳转到下载的视图函数中 -->
            <a href="{% url 'file_zidingyi:file_diy_download' %}?id={{file.id}}">下载普通文件</a>
        </li>
        
        {% endfor %}
    </ul>
</body>
</html>

urls

from django.contrib import admin
from django.urls import path,include
from file_app import views
app_name = 'file_zidingyi'
urlpatterns = [
    path('file_admin/<int:pk>/',views.file_admin),
    path('file_advance/<int:pk>/',views.file_advance),
    path('file_diy/',views.file_diy, name='file_diy'),
    path('file_diy_list/',views.file_diy_list),
    path('file_diy_download/',views.file_diy_download,name='file_diy_download'),
]

效果展示
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

想成为数据分析师的开发工程师

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值