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这两个接口实现的底层结构,他们利用了搜索树与哈希表查找效率高这一特点,是一种专门用来进行搜索操作的容器或数据结构。本篇文章就让我们一起来梳理这两个接口的…...

【Python】 -- 趣味代码 - 小恐龙游戏
文章目录 文章目录 00 小恐龙游戏程序设计框架代码结构和功能游戏流程总结01 小恐龙游戏程序设计02 百度网盘地址00 小恐龙游戏程序设计框架 这段代码是一个基于 Pygame 的简易跑酷游戏的完整实现,玩家控制一个角色(龙)躲避障碍物(仙人掌和乌鸦)。以下是代码的详细介绍:…...

Linux 文件类型,目录与路径,文件与目录管理
文件类型 后面的字符表示文件类型标志 普通文件:-(纯文本文件,二进制文件,数据格式文件) 如文本文件、图片、程序文件等。 目录文件:d(directory) 用来存放其他文件或子目录。 设备…...
React Native 开发环境搭建(全平台详解)
React Native 开发环境搭建(全平台详解) 在开始使用 React Native 开发移动应用之前,正确设置开发环境是至关重要的一步。本文将为你提供一份全面的指南,涵盖 macOS 和 Windows 平台的配置步骤,如何在 Android 和 iOS…...
DockerHub与私有镜像仓库在容器化中的应用与管理
哈喽,大家好,我是左手python! Docker Hub的应用与管理 Docker Hub的基本概念与使用方法 Docker Hub是Docker官方提供的一个公共镜像仓库,用户可以在其中找到各种操作系统、软件和应用的镜像。开发者可以通过Docker Hub轻松获取所…...

【HarmonyOS 5.0】DevEco Testing:鸿蒙应用质量保障的终极武器
——全方位测试解决方案与代码实战 一、工具定位与核心能力 DevEco Testing是HarmonyOS官方推出的一体化测试平台,覆盖应用全生命周期测试需求,主要提供五大核心能力: 测试类型检测目标关键指标功能体验基…...
系统设计 --- MongoDB亿级数据查询优化策略
系统设计 --- MongoDB亿级数据查询分表策略 背景Solution --- 分表 背景 使用audit log实现Audi Trail功能 Audit Trail范围: 六个月数据量: 每秒5-7条audi log,共计7千万 – 1亿条数据需要实现全文检索按照时间倒序因为license问题,不能使用ELK只能使用…...

【SQL学习笔记1】增删改查+多表连接全解析(内附SQL免费在线练习工具)
可以使用Sqliteviz这个网站免费编写sql语句,它能够让用户直接在浏览器内练习SQL的语法,不需要安装任何软件。 链接如下: sqliteviz 注意: 在转写SQL语法时,关键字之间有一个特定的顺序,这个顺序会影响到…...
WEB3全栈开发——面试专业技能点P2智能合约开发(Solidity)
一、Solidity合约开发 下面是 Solidity 合约开发 的概念、代码示例及讲解,适合用作学习或写简历项目背景说明。 🧠 一、概念简介:Solidity 合约开发 Solidity 是一种专门为 以太坊(Ethereum)平台编写智能合约的高级编…...
高效线程安全的单例模式:Python 中的懒加载与自定义初始化参数
高效线程安全的单例模式:Python 中的懒加载与自定义初始化参数 在软件开发中,单例模式(Singleton Pattern)是一种常见的设计模式,确保一个类仅有一个实例,并提供一个全局访问点。在多线程环境下,实现单例模式时需要注意线程安全问题,以防止多个线程同时创建实例,导致…...
uniapp 字符包含的相关方法
在uniapp中,如果你想检查一个字符串是否包含另一个子字符串,你可以使用JavaScript中的includes()方法或者indexOf()方法。这两种方法都可以达到目的,但它们在处理方式和返回值上有所不同。 使用includes()方法 includes()方法用于判断一个字…...