1. 文件上传和下载环境搭建
- 创建django项目和子应用
- urls中包含子应用,在子应用中创建urls.py
- 配置数据库sqlite3(默认就是,无需配置)
- 配置settings,上传文件目录
- 编写模型代码(下面给出)
- 模型的预迁移和迁移
- Nacicat创建数据库,然后查看表
- 根目录下创建文件夹media
- 可以翻阅本专栏,前面都有介绍
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'),
]
效果展示