Django-文件上传
## Django文件上传需要考虑的重要事项
> 文件或图片一般通过表单进行。用户在前端点击文件上传,然后以POST方式将数据和文件提交到服务器。服务器在接收到POST请求后需要将其存储在服务器上的某个地方。Django默认的存储地址是相对于根目录的/media/文件夹,存储的默认文件名就是文件本来的名字。上传的文件如果不大于2.5MB,会先存入服务器内存中,然后再写入磁盘。如果上传的文件很大,Django会把文件先存入临时文件,再写入磁盘。
>
> Django默认处理方式会出现一个问题,所有文件都存储在一个文件夹里。不同用户上传的有相同名字的文件可能会相互覆盖。另外用户还可能上传一些不安全的文件如js和exe文件,我们必需对允许上传文件的类型进行限制。因此我们在利用Django处理文件上传时必需考虑如下3个因素:
- 设置存储上传文件的文件夹地址
- 对上传文件进行重命名
- 对可接受的文件类型进行限制(表单验证)
`以上事项对于上传图片是同样适用的。`
## Django文件上传的3种常见方式
- 使用一般的自定义表单上传,在视图中手动编写代码处理上传的文件
- 使用由模型创建的表单(ModelForm)上传,使用`form.save()`方法自动存储
- 使用Ajax实现文件异步上传,上传页面无需刷新即可显示新上传的文件
## 创建模型
> 我们上传的文件都会放在/media/文件夹里。我们还需要使用css和js这些静态文件,所以需要设置STATIC_URL。
```python
#file_project/settings.py
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'file_upload',# 新增
]
STATIC_URL = '/static/'
STATICFILES_DIRS = [os.path.join(BASE_DIR, "static"), ]
MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
MEDIA_URL = '/media/'
#file_project/urls.py
from django.contrib import admin
from django.urls import path, include
from django.conf import settings
from django.conf.urls.static import static
urlpatterns = [
path('admin/', admin.site.urls),
path('file/', include("file_upload.urls")),
] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
```
> 使用Django上传文件创建模型不是必需,然而如果我们需要对上传文件进行系统化管理,模型还是很重要的。我们的File模型包括`file`和`upload_method`两个字段。我们通过`upload_to`选项指定了文件上传后存储的地址,并对上传的文件名进行了重命名。
```python
#file_upload/models.py
from django.db import models
import os
import uuid
# Create your models here.
# Define user directory path
def user_directory_path(instance, filename):
ext = filename.split('.')[-1]
filename = '{}.{}'.format(uuid.uuid4().hex[:10], ext)
return os.path.join("files", filename)
class File(models.Model):
file = models.FileField(upload_to=user_directory_path, null=True)
upload_method = models.CharField(max_length=20, verbose_name="Upload Method")
```
> 如果你不使用`ModelForm`,你还需要手动编写代码存储上传文件。
## URLConf配置
> 普通表单上传,ModelForm上传和显示文件清单配置
```python
#file_upload/urls.py
from django.urls import re_path, path
from . import views
# namespace
app_name = "file_upload"
urlpatterns = [
# Upload File Without Using Model Form
re_path(r'^upload1/$', views.file_upload, name='file_upload'),
# Upload Files Using Model Form
re_path(r'^upload2/$', views.model_form_upload, name='model_form_upload'),
# View File List
path('file/', views.file_list, name='file_list'),
]
```
## 使用一般表单上传文件
> 我们先定义一个一般表单`FileUploadForm`,并通过clean方法对用户上传的文件进行验证,如果上传的文件名不以jpg, pdf或xlsx结尾,将显示表单验证错误信息。
```python
#file_upload/forms.py
from django import forms
from .models import File
# Regular form
class FileUploadForm(forms.Form):
file = forms.FileField(widget=forms.ClearableFileInput(attrs={'class': 'form-control'}))
upload_method = forms.CharField(label="Upload Method", max_length=20,
widget=forms.TextInput(attrs={'class': 'form-control'}))
def clean_file(self):
file = self.cleaned_data['file']
ext = file.name.split('.')[-1].lower()
if ext not in ["jpg", "pdf", "xlsx"]:
raise forms.ValidationError("Only jpg, pdf and xlsx files are allowed.")
# return cleaned data is very important.
return file
```
> 使用clean方法对表单字段进行验证时,别忘了return验证过的数据,即`cleaned_data`。只有返回了cleaned_data, 视图中才可以使用form.cleaned_data.get(‘xxx’)获取验证过的数据。
>
> 对应一般文件上传的视图`file_upload`方法如下所示。当用户的请求方法为POST时,我们通过`form.cleaned_data.get('file')`获取通过验证的文件,并调用自定义的`handle_uploaded_file`方法来对文件进行重命名,写入文件。如果用户的请求方法不为POST,则渲染一个空的`FileUploadForm`在`upload_form.html`里。我们还定义了一个`file_list`方法来显示文件清单。
```python
#file_upload/views.py
from django.shortcuts import render, redirect
from .models import File
from .forms import FileUploadForm, FileUploadModelForm
import os
import uuid
from django.http import JsonResponse
from django.template.defaultfilters import filesizeformat
# Create your views here.
# Show file list
def file_list(request):
files = File.objects.all().order_by("-id")
return render(request, 'file_upload/file_list.html', {'files': files})
# Regular file upload without using ModelForm
def file_upload(request):
if request.method == "POST":
form = FileUploadForm(request.POST, request.FILES)
if form.is_valid():
# get cleaned data
upload_method = form.cleaned_data.get("upload_method")
raw_file = form.cleaned_data.get("file")
new_file = File()
new_file.file = handle_uploaded_file(raw_file)
new_file.upload_method = upload_method
new_file.save()
return redirect("/file/")
else:
form = FileUploadForm()
return render(request, 'file_upload/upload_form.html',
{'form': form, 'heading': 'Upload files with Regular Form'}
)
def handle_uploaded_file(file):
ext = file.name.split('.')[-1]
file_name = '{}.{}'.format(uuid.uuid4().hex[:10], ext)
# file path relative to 'media' folder
file_path = os.path.join('files', file_name)
absolute_file_path = os.path.join('media', 'files', file_name)
directory = os.path.dirname(absolute_file_path)
if not os.path.exists(directory):
os.makedirs(directory)
with open(absolute_file_path, 'wb+') as destination:
for chunk in file.chunks():
destination.write(chunk)
return file_path
```
- `handle_uploaded_file`方法里文件写入地址必需是包含`/media`/的绝对路径,如果/media/files/xxxx.jpg,而该方法返回的地址是相对于/media/文件夹的地址,如/files/xxx.jpg。存在数据中字段的是相对地址,而不是绝对地址。
- 构建文件写入绝对路径时请用`os.path.join`方法,因为不同系统文件夹分隔符不一样。写入文件前一个良好的习惯是使用`os.path.exists`检查目标文件夹是否存在,如果不存在先创建文件夹,再写入。
> 上传表单模板`upload_form.html`代码如下:
```html
#file_upload/templates/upload_form.html
{% extends "file_upload/base.html" %}
{% block content %}
{% if heading %}
<h3>{{ heading }}</h3>
{% endif %}
<form action="" method="post" enctype="multipart/form-data" >
{% csrf_token %}
{{ form.as_p }}
<button class="btn btn-info form-control " type="submit" value="submit">Upload</button>
</form>
{% endblock %}
```
> 显示文件清单模板`file_list.html`代码如下所示:
```html
# file_upload/templates/file_list.html
{% extends "file_upload/base.html" %}
{% block content %}
<h3>File List</h3>
<p> <a href="/file/upload1/">RegularFormUpload</a> | <a href="/file/upload2/">ModelFormUpload</a>
| <a href="/file/upload3/">AjaxUpload</a></p>
{% if files %}
<table class="table table-striped">
<tbody>
<tr>
<td>Filename & URL</td>
<td>Filesize</td>
<td>Upload Method</td>
</tr>
{% for file in files %}
<tr>
<td><a href="{{ file.file.url }}">{{ file.file.url }}</a></td>
<td>{{ file.file.size | filesizeformat }}</td>
<td>{{ file.upload_method }}</td>
</tr>
{% endfor %}
</tbody>
</table>
{% else %}
<p>No files uploaded yet. Please click <a href="{% url 'file_upload:file_upload' %}">here</a>
to upload files.</p>
{% endif %}
{% endblock %}
```
- 对于上传的文件我们可以调用`file.url`, `file.name`和`file.size`来查看上传文件的链接,地址和大小。
- 上传文件的大小默认是以B显示的,数字非常大。使用Django模板过滤器`filesizeformat`可以将文件大小显示为人们可读的方式,如MB,KB。
## 使用ModelForm上传文件
> 在模型中通过`upload_to`选项自定义了用户上传文件存储地址,并对文件进行了重命名。我们首先要自定义自己的`FileUploadModelForm`,由File模型重建的。代码如下所示:
```python
#file_upload/forms.py
from django import forms
from .models import File
# Model form
class FileUploadModelForm(forms.ModelForm):
class Meta:
model = File
fields = ('file', 'upload_method',)
widgets = {
'upload_method': forms.TextInput(attrs={'class': 'form-control'}),
'file': forms.ClearableFileInput(attrs={'class': 'form-control'}),
}
def clean_file(self):
file = self.cleaned_data['file']
ext = file.name.split('.')[-1].lower()
if ext not in ["jpg", "pdf", "xlsx"]:
raise forms.ValidationError("Only jpg, pdf and xlsx files are allowed.")
# return cleaned data is very important.
return file
```
> 使用`ModelForm`处理文件上传的视图`model_form_upload`方法非常简单,只需调用`form.save()`即可,无需再手动编写代码写入文件。
```python
#file_upload/views.py
from django.shortcuts import render, redirect
from .models import File
from .forms import FileUploadForm, FileUploadModelForm
import os
import uuid
from django.http import JsonResponse
from django.template.defaultfilters import filesizeformat
# Create your views here.
# Upload File with ModelForm
def model_form_upload(request):
if request.method == "POST":
form = FileUploadModelForm(request.POST, request.FILES)
if form.is_valid():
form.save() # 一句话足以
return redirect("/file/")
else:
form = FileUploadModelForm()
return render(request, 'file_upload/upload_form.html',
{'form': form,'heading': 'Upload files with ModelForm'}
)
```
相关文章:
Django-文件上传
## Django文件上传需要考虑的重要事项 > 文件或图片一般通过表单进行。用户在前端点击文件上传,然后以POST方式将数据和文件提交到服务器。服务器在接收到POST请求后需要将其存储在服务器上的某个地方。Django默认的存储地址是相对于根目录的/media/文件夹&…...
[Meachines] [Easy] valentine SSL心脏滴血+SSH-RSA解密+trp00f自动化权限提升+Tmux进程劫持权限提升
信息收集 IP AddressOpening Ports10.10.10.79TCP:22,80,443 $ nmap 10.10.10.79 --min-rate 1000 -sC -sV PORT STATE SERVICE VERSION 22/tcp open ssh OpenSSH 5.9p1 Debian 5ubuntu1.10 (Ubuntu Linux; protocol 2.0) | ssh-hostkey: | 1024 96:4c:51:42:…...
利用单张/多张图内参数标定 OpenCV Python
E:\OpenCV_py_ws\opencv相机标定\图片\calib-JT.py #!/usr/bin/env python # -*- coding: utf-8 -*- # @Time : 2023/11/21 16:05 # @File : calib.py # @Software: import cv2 import numpy as np import glob from datetime import datetimenp.set_printoptions(supp…...
The Llama 3 Herd of Models 第7部分视觉实验部分全文
第1,2,3部分,介绍、概览和预训练 第4部分,后训练 第5部分,结果 第6部分,推理 7 Vision Experiments 我们进行了一系列的实验,在这些实验中,我们通过一种由两个主要阶段组成的合成方法将视觉识别能力整合到Llama 3中。首先,我们通过在大量图像-文本对上引入和训练两种…...
亚信安慧AntDB-T:使用Brin索引提升OLAP查询性能以及节省磁盘空间
前 言 在这个信息量爆炸的时代,数据库面临着海量数据的挑战,如何提升OLAP业务的查询性能、如何节省磁盘空间等问题已经成为了数据库的痛点之所在。本篇着重介绍亚信安慧AntDB-T中Brin索引的实现过程以及应用在OLAP业务中带来的性能提升和存储降低。 亚…...
web渗透测试常用命令
Web Application TTPs HPING3 DoS hping3 targetiP --flood --frag --spoof ip --destport # --synHydra Online Brute Force hydra -1 ftp -P words -v targetiP ftpDownload HTTP File and Execute...
Kylin系列(二)使用
接上一章《Kylin系列(一)入门》 1. Kylin使用 1.1. 数据准备 1.1.1. 数据导入 在使用Apache Kylin时,数据导入是一个非常重要的环节,因为它直接影响到Kylin的性能、稳定性和易用性。以下是关于Apache Kylin数据导入的一些详细介绍: 导入数据的准备 在开始导入数据之前…...
CI/CD——CI持续集成实验
目录 一. 安装Docker 二. 部署Jenkins 三. 配置邮箱 四. Harbor部署 五. Nexus Repository部署 五. sonarqube安装 六. 配置Docker 七. jenkins系统配置sonarqube 八. 配置pipeline 九. 构建并集成 一. 安装Docker docker-ce镜像_docker-ce下载地址_docker-ce安装教程…...
2.4 大模型数据基础:预训练阶段数据详解 ——《带你自学大语言模型》系列
本系列目录 《带你自学大语言模型》系列部分目录及计划,完整版目录见:带你自学大语言模型系列 —— 前言 第一部分 走进大语言模型(科普向) 第一章 走进大语言模型 1.1 从图灵机到GPT,人工智能经历了什么…...
Kali Linux——网络安全的瑞士军刀
一、引言 在网络安全的领域中,Kali Linux 宛如一把强大而全能的瑞士军刀,为安全研究人员和专业人士提供了丰富的工具和资源。本文将深入探讨 Kali Linux 的特点、优势、常用工具以及实际应用场景,带您领略这一强大操作系统的魅力。 二、Kal…...
UML建模-测试用例
用例可用于测试系统的正确性和有效性。 正确性表明系统的实现符合规格说明。有效性保证开发的系统是用户真正需要的系统。有效性检查一般在 系统开发之前进行。当用例模型构造完成后,开发者将模型交给用户讨论,由用户检查模型能否满足他们对系统的需求。…...
Python知识点:如何使用Socket模块进行网络编程
Python 的 socket 模块提供了一个底层网络接口,允许你通过编程进行网络通信。使用 socket 模块可以编写客户端和服务器端程序,从而实现数据在网络上的传输。以下是如何使用 socket 模块进行网络编程的详细说明。 1. 创建一个 Socket 首先,你…...
培训第二十一天(mysql用户创建与授权、角色创建)
上午 1、环境准备 [rootmysql ~]# rm -rf /etc/my.cnf //清空/etc目录下的my.cnf[rootmysql ~]# yum -y remove mariadb //移除mariadb[rootmysql ~]# find / -name "*mysql*" -exec rm -rf {} \; //删除mysql所有遗留文件 2、安装mysql绿包 [rootmysql ~]…...
makefile基本语法
在编写复杂的程序项目时,Makefile 是一个非常有用的工具,它能自动化构建过程。以下是一些基本的 Makefile 语法介绍: 基本结构: target: dependenciescommandtarget:构建目标,通常是一个文件,如…...
白骑士的PyCharm教学实战项目篇 4.4 大数据处理与分析
系列目录 上一篇:白骑士的PyCharm教学实战项目篇 4.3 自动化测试与持续集成 随着数据量的爆炸性增长,大数据处理与分析成为现代数据科学的重要课题。PyCharm提供了强大的功能,可以帮助开发者高效地进行大数据环境的配置与连接…...
无人机之民用无人机用途分类篇
一、航拍无人机 用于航拍摄影和电影制作,提供空中视角的拍摄服务。可用于电影制作、广告拍摄、房地产销售等。 二、物流无人机 用于快递和货物运输,提高物流效率,可以到达传统配送方式难以覆盖的地区,在突发事件如自然灾害、疫…...
Android10 修改设备名称
A10和A12的设备名称修改是不同的,A10设备名称修改分好几个位置 修改wifi默认名称 在framework/base模块下 diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml index 9041a7c3a14..7a1e63688c4 100644 --- a/core/res/res/values/…...
go testing 包
Go语言的testing包提供了一套丰富的测试工具,用于编写和运行测试用例。以下是testing包中一些常用的函数和类型: func TestMain(m *testing.M): 这是一个特殊的函数,用于执行测试的主函数。如果定义了TestMain,那么在运行go test时…...
基于phpstudy的靶场搭建和github加速
微软商店下载 watt toolkit,然后在侧边栏选择网络加速,勾选 github,就可以快速访问 github 1、下载搭建 sqlilabs github 找到 sqlilabs 靶场,点击 code,下载 zip解压之后,整体移动到 phpstudy_pro 文件夹…...
【数据结构】Map与Set
前言 前两篇文章我们研究了二叉搜索树与哈希表的结构与特点,他们二者是Map与Set这两个接口实现的底层结构,他们利用了搜索树与哈希表查找效率高这一特点,是一种专门用来进行搜索操作的容器或数据结构。本篇文章就让我们一起来梳理这两个接口的…...
C++实现分布式网络通信框架RPC(3)--rpc调用端
目录 一、前言 二、UserServiceRpc_Stub 三、 CallMethod方法的重写 头文件 实现 四、rpc调用端的调用 实现 五、 google::protobuf::RpcController *controller 头文件 实现 六、总结 一、前言 在前边的文章中,我们已经大致实现了rpc服务端的各项功能代…...
MongoDB学习和应用(高效的非关系型数据库)
一丶 MongoDB简介 对于社交类软件的功能,我们需要对它的功能特点进行分析: 数据量会随着用户数增大而增大读多写少价值较低非好友看不到其动态信息地理位置的查询… 针对以上特点进行分析各大存储工具: mysql:关系型数据库&am…...
条件运算符
C中的三目运算符(也称条件运算符,英文:ternary operator)是一种简洁的条件选择语句,语法如下: 条件表达式 ? 表达式1 : 表达式2• 如果“条件表达式”为true,则整个表达式的结果为“表达式1”…...
CRMEB 框架中 PHP 上传扩展开发:涵盖本地上传及阿里云 OSS、腾讯云 COS、七牛云
目前已有本地上传、阿里云OSS上传、腾讯云COS上传、七牛云上传扩展 扩展入口文件 文件目录 crmeb\services\upload\Upload.php namespace crmeb\services\upload;use crmeb\basic\BaseManager; use think\facade\Config;/*** Class Upload* package crmeb\services\upload* …...
实现弹窗随键盘上移居中
实现弹窗随键盘上移的核心思路 在Android中,可以通过监听键盘的显示和隐藏事件,动态调整弹窗的位置。关键点在于获取键盘高度,并计算剩余屏幕空间以重新定位弹窗。 // 在Activity或Fragment中设置键盘监听 val rootView findViewById<V…...
vue3+vite项目中使用.env文件环境变量方法
vue3vite项目中使用.env文件环境变量方法 .env文件作用命名规则常用的配置项示例使用方法注意事项在vite.config.js文件中读取环境变量方法 .env文件作用 .env 文件用于定义环境变量,这些变量可以在项目中通过 import.meta.env 进行访问。Vite 会自动加载这些环境变…...
Java线上CPU飙高问题排查全指南
一、引言 在Java应用的线上运行环境中,CPU飙高是一个常见且棘手的性能问题。当系统出现CPU飙高时,通常会导致应用响应缓慢,甚至服务不可用,严重影响用户体验和业务运行。因此,掌握一套科学有效的CPU飙高问题排查方法&…...
【生成模型】视频生成论文调研
工作清单 上游应用方向:控制、速度、时长、高动态、多主体驱动 类型工作基础模型WAN / WAN-VACE / HunyuanVideo控制条件轨迹控制ATI~镜头控制ReCamMaster~多主体驱动Phantom~音频驱动Let Them Talk: Audio-Driven Multi-Person Conversational Video Generation速…...
【Redis】笔记|第8节|大厂高并发缓存架构实战与优化
缓存架构 代码结构 代码详情 功能点: 多级缓存,先查本地缓存,再查Redis,最后才查数据库热点数据重建逻辑使用分布式锁,二次查询更新缓存采用读写锁提升性能采用Redis的发布订阅机制通知所有实例更新本地缓存适用读多…...
C++课设:简易日历程序(支持传统节假日 + 二十四节气 + 个人纪念日管理)
名人说:路漫漫其修远兮,吾将上下而求索。—— 屈原《离骚》 创作者:Code_流苏(CSDN)(一个喜欢古诗词和编程的Coder😊) 专栏介绍:《编程项目实战》 目录 一、为什么要开发一个日历程序?1. 深入理解时间算法2. 练习面向对象设计3. 学习数据结构应用二、核心算法深度解析…...
