django多个html文件上传,Django高级(七):多文件上传

uploadMulti一次上传多个文件/图片

0.写在前面:

In this tutorial I will guide you through the steps to implement an AJAX multiple file upload with Django using jQuery. For this tutorial we will be using a specific plug-in called jQuery File Upload, which takes care of the server communication using AJAX and also the compatibility with different browsers.

Now you will see that the jQuery File Upload comes with several script files, they all have a purpose and you will only need some of them for certain features.

基本settings.py配置

# /root/suyn_website/uploadFiles/uploadFiles/settings.py

BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))

#/root/suyn_website/uploadFiles

INSTALLED_APPS = [

'django.contrib.admin',

'django.contrib.auth',

'django.contrib.contenttypes',

'django.contrib.sessions',

'django.contrib.messages',

'django.contrib.staticfiles',

'UploadMulti', #

]

注:基本配置和上篇‘uploadOne一次上传一个文件’类似

应用UploadMulti,文件夹树:

root@ubuntu:~/suyn_website/uploadFiles# tree

.

├── LICENSE

├── manage.py

├── media

│ └── photos

├── README.md

├── static

│ ├── css

│ │ ├── bootstrap.min.css

│ │ └── bootstrap.min.css.map

│ ├── fonts

│ │ ├── glyphicons-halflings-regular.eot

│ │ ├── glyphicons-halflings-regular.svg

│ │ ├── glyphicons-halflings-regular.ttf

│ │ ├── glyphicons-halflings-regular.woff

│ │ └── glyphicons-halflings-regular.woff2

│ └── js

│ ├── bootstrap.min.js

│ ├── jquery-3.2.0.min.js

│ └── jquery-file-upload

│ ├── jquery.fileupload.js

│ ├── jquery.iframe-transport.js

│ └── vendor

│ └── jquery.ui.widget.js

├── staticRoot

├── templates

│ ├── base.html

│ ├── home.html

│ └── includes

│ └── header.html

├── uploadFiles

│ ├── __init__.py

│ ├── settings.py

│ ├── urls.py

│ ├── wsgi.py

└── UploadMulti

├── admin.py

├── apps.py

├── forms.py

├── __init__.py

├── migrations

│ ├── 0001_initial.py

│ ├── 0001_initial.pyc

│ ├── __init__.py

│ └── __init__.pyc

├── models.py

├── static

│ └── UploadMulti

│ └── js

│ ├── basic-upload.js

│ ├── drag-and-drop-upload.js

│ └── progress-bar-upload.js

├── templates

│ └── UploadMulti

│ ├── base.html

│ ├── basic_upload

│ │ └── index.html

│ ├── drag_and_drop_upload

│ │ └── index.html

│ └── progress_bar_upload

│ └── index.html

├── tests.py

├── urls.py

└── views.py

1.home主页只是简单的介绍

主页模板继承:

uploadFiles/templates/home.html继承自uploadFiles/templates/base.html的'block content'

c8fd2c24be07?d=123

127.0.0.0:8000

##### uploadFiles/uploadFiles/urls.py

from django.conf.urls import url,include

from django.contrib import admin

from django.conf.urls.static import static

from uploadFiles import settings

from django.views.generic import TemplateView

urlpatterns = [

url(r'^admin/', admin.site.urls),

#url(r'^UploadOne/',include('UploadOne.urls')),

url(r'^$', TemplateView.as_view(template_name='home.html'), name='home'), #这部分重点看home.html主页

url(r'^UploadMulti/',include('UploadMulti.urls',namespace='UploadMulti')),

]

if settings.DEBUG:

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

##### uploadFiles/templates/home.html

{% extends 'base.html' %} ##

{% block content %}

See the example live clicking in the Photos menu.


Static Assets

Following the list of static assets used in this example

{% endblock %}

##### uploadFiles/templates/base.html

{% load static %}

{% block title %}Photos Library - Simple is Better Than Complex{% endblock %}

.page-header {

margin-top: 0;

}

{% include 'includes/header.html' %} ##

{% block content %}

{% endblock %}

{### Bootstrap and jQuery in the base template,

## and the jQuery File Upload plug-in will be added using the {% block javascript %} #}

##引入支持的Jquery脚本

##引入支持的bootstrap脚本

{% block javascript %}

{% endblock %}

##### uploadFiles/templates/includes/header.html

2.Photos涉及有三个链接,针对三种多文件上传方式。

Basic Upload

Progress Bar Upload

Drag and Drop Upload

三种方式模板继承:

各自的uploadFiles/UploadMulti/templates/UploadMulti/basic_upload/index.html继承自uploadFiles/UploadMulti/templates/UploadMulti/base.html的'block photocontent'和'bock title'('Photos/xxx'指定三种方式)。

上面的base.html的'Example'包含三种方式的链接请求,分别指向三种视图函数,该base.html再继承自uploadFiles/templates/base.html(包含includes/header.html)。

关键的一点是,三种方式的Index.html文件都包含与服务器通信的js脚本文件,是继承自uploadFiles/templates/base.html的'block javascript'。

一些公共代码及模型表单创建:

##### uploadFiles/UploadMulti/urls.py

# 关于'Class-Based Views vs. Function-Based Views'可参看其他文章

from django.conf.urls import url

from . import views

app_name = 'UploadMulti'

urlpatterns = [

url(r'^clear/$', views.clear_database, name='clear_database'),

url(r'^basic-upload/$', views.BasicUploadView.as_view(), name='basic_upload'),

url(r'^progress-bar-upload/$', views.ProgressBarUploadView.as_view(), name='progress_bar_upload'),

url(r'^drag-and-drop-upload/$', views.DragAndDropUploadView.as_view(), name='drag_and_drop_upload'),

]

##### uploadFiles/UploadMulti/models.py

class Photo(models.Model):

title = models.CharField(max_length=255, blank=True)

file = models.FileField(upload_to='photos/') ##FileField 文件图片都可以上传

uploaded_at = models.DateTimeField(auto_now_add=True)

##### uploadFiles/UploadMulti/forms.py

from django import forms

from .models import Photo

class PhotoForm(forms.ModelForm):

class Meta:

model = Photo

fields = ('file', )

2.0. 写在前面:关于'clear_database'

##### views.py

def clear_database(request):

for photo in Photo.objects.all():

photo.file.delete()

photo.delete()

return redirect(request.POST.get('next'))

##### UploadMulti/base.html

{% extends 'base.html' %}

{% block content %}

{# #### 这里的表单实现对上传文件/图片的清空,同时清空本地 #}

{% csrf_token %}

Clear Database

Photos

/ {% block title %}{% endblock %} ###

Examples

Basic Upload

Progress Bar Upload

Drag and Drop Upload

{% block photos_content %} ###

{% endblock %}

{% endblock %}

2.1. Basic Upload

c8fd2c24be07?d=123

http://127.0.0.1:8000/UploadMulti/basic-upload/

We are using a basic Class-Based View, defining two request processing for the GET and POST methods. For the POST, it is where the upload handling happens, using Django’s Model Forms. When we call form.save(), Django will create a Photo instance and save the file in the file system.

2.1.1.介绍下用到的jquery-file-upload插件功能:

{% block javascript %} ##from templates/base.html用到了jquery-file-upload插件

{# JQUERY FILE UPLOAD SCRIPTS #}

{# PHOTOS PAGE SCRIPTS #}

{% endblock %}

jquery.ui.widget.js It’s a dependency for the plug-in

jquery.iframe-transport.js The Iframe Transport is required for browsers without support for XHR file uploads

jquery.fileupload.js The basic File Upload plug-in

And finally the script basic-upload.js is where we will implement our photo upload.

2.1.2.介绍下index.html页面上几个代码块:

{% block photos_content %} ##from UploadMulti/base.html

{# 1. BUTTON TO TRIGGER THE ACTION #}

Upload photos

{# 2. FILE INPUT TO BE USED BY THE PLUG-IN #}

style="display: none;"

data-url="{% url 'UploadMulti:basic_upload' %}"

data-form-data='{"csrfmiddlewaretoken": "{{ csrf_token }}"}'>

{# 3. TABLE TO DISPLAY THE UPLOADED PHOTOS #}

Photo

{% for photo in photos %}

{{ photo.file.name }}

{% endfor %}

{% endblock %}

block 1 of the snippet, is the button to start the workflow. We will hook into the css class .js-upload-photos to open the file explorer window.

Block 2 is the most important part of the page. It’s the the file input that will be used to load the jQuery File Upload component. A few things to note:

The name of the input must match with the *Model Form Field(FileField). 也就是,name属性必须和‘file = models.FileField(upload_to='photos/')’一致。

The multiple attribute will enable multiple file selection in the file explorer window.

The data-url attribute must point to the route/view where the file form will be processed.

The data-form-data attribute should be defined exactly this way! This line is important so to instruct the plug-in to send the file along with the csrf middleware token.

block 3 is just a regular table displaying the photos.

##### uploadFiles/UploadMulti/views.py

from django.shortcuts import render,redirect

from django.http import JsonResponse

from django.views import View

import time

from .forms import PhotoForm

from .models import Photo

# Create your views here.

class BasicUploadView(View):

def get(self, request):

photos_list = Photo.objects.all()

return render(self.request, 'UploadMulti/basic_upload/index.html', {'photos': photos_list}) ##渲染index.html,传递文件/图像对象

def post(self, request):

form = PhotoForm(self.request.POST, self.request.FILES)

if form.is_valid():

photo = form.save() ##保存到本地

data = {'is_valid': True, 'name': photo.file.name, 'url': photo.file.url}

else:

data = {'is_valid': False}

return JsonResponse(data) ###JSON格式的data,传递给js

##### uploadFiles/UploadMulti/templates/UploadMulti/basic_upload/index.html

{% extends 'UploadMulti/base.html' %} ##

{% load static %}

{% block title %}Basic Upload{% endblock %} ##from UploadMulti/base.html

##(公共代码:各自选择自己的upload js实现)

{% block javascript %} ##from templates/base.html用到了jquery-file-upload插件

{# JQUERY FILE UPLOAD SCRIPTS #}

{# PHOTOS PAGE SCRIPTS #}

{% endblock %}

{% block photos_content %} ##from UploadMulti/base.html

Upload photos

{#### id="fileupload"会在js函数中进一步处理,FILE INPUT TO BE USED BY THE PLUG-IN #}

style="display: none;"

data-url="{% url 'UploadMulti:basic_upload' %}"

data-form-data='{"csrfmiddlewaretoken": "{{ csrf_token }}"}'>

## 罗列出已经上传的文件/图片(公共代码)

Photo

{% for photo in photos %}

{{ photo.file.name }}

{% endfor %}

{% endblock %}

##### uploadFiles/UploadMulti/static/UploadMulti/js/basic-upload.js

$(function () {

/* 1. OPEN THE FILE EXPLORER WINDOW */

$(".js-upload-photos").click(function () {

$("#fileupload").click();

});

/* 2. INITIALIZE THE FILE UPLOAD COMPONENT */

$("#fileupload").fileupload({ ####fileupload

dataType: 'json',

done: function (e, data) { /* 3. PROCESS THE RESPONSE FROM THE SERVER 这里的data来自于JsonResponse传来的data*/

if (data.result.is_valid) {

$("#gallery tbody").prepend(

"

" + data.result.name + ""

)

}

}

});

});

2.1.3. 介绍data在post方法和js脚本函数中的传递:

def post(self, request):

form = PhotoForm(self.request.POST, self.request.FILES)

if form.is_valid():

photo = form.save() ##保存到本地

data = {'is_valid': True, 'name': photo.file.name, 'url': photo.file.url}

else:

data = {'is_valid': False}

return JsonResponse(data) ###JSON格式的data,传递给js

/* 2. INITIALIZE THE FILE UPLOAD COMPONENT */

$("#fileupload").fileupload({ ####fileupload

dataType: 'json',

done: function (e, data) { /* 3. PROCESS THE RESPONSE FROM THE SERVER 这里的data来自于JsonResponse传来的data*/

if (data.result.is_valid) {

$("#gallery tbody").prepend(

"

" + data.result.name + ""

)

}

}

});

});

This JsonResponse(post method) will end up in the data parameter,

passed to the anonymous function hooked to the done event of the File Upload component.

See what we are doing here? When we are accessing data.result.name, we are accessing the name we returned in the JsonResponse.

So, let’s say, if we returned:

return JsonResponse({'message': 'Success'})

We would be able to catch it inside the done function, this way:

done: function (e, data) {

if (data.result.message === 'Success') {

// do something...

}

}

2.2. Progress Bar Upload

c8fd2c24be07?d=123

http://127.0.0.1:8000/UploadMulti/progress-bar-upload/

##### views.py

一样

##### index.html

{# ####这里是页面差别,显示上传的进度条,It’s a Bootstrap modal #}

{% endblock %}

##### progress-bar-upload.js

$(function () {

$(".js-upload-photos").click(function () {

$("#fileupload").click();

});

$("#fileupload").fileupload({

dataType: 'json',

sequentialUploads: true, /* 1. SEND THE FILES ONE BY ONE 这个属性指示该组件一次发送一个文件*/

start: function (e) { /* 2. WHEN THE UPLOADING PROCESS STARTS, SHOW THE MODAL */

$("#modal-progress").modal("show");

},

stop: function (e) { /* 3. WHEN THE UPLOADING PROCESS FINALIZE, HIDE THE MODAL */

$("#modal-progress").modal("hide");

},

progressall: function (e, data) { #/* 4. UPDATE THE PROGRESS BAR */

var progress = parseInt(data.loaded / data.total * 100, 10); ##

var strProgress = progress + "%";

$(".progress-bar").css({"width": strProgress});

$(".progress-bar").text(strProgress);

},

done: function (e, data) {

if (data.result.is_valid) {

$("#gallery tbody").prepend(

"

" + data.result.name + ""

)

}

}

});

});

注:What we are doing here basically is :

showing the loading modal when the upload starts,

closing it when it finalizes,

meanwhile we update the percentage in the progress bar.

2.3. Drag and Drop Upload

c8fd2c24be07?d=123

http://127.0.0.1:8000/UploadMulti/drag-and-drop-upload/

##### views.py

一样

##### index.html

{# ### 这里是差异,显示拖拽位置部分,不在是‘Upload photos’按钮 #}

Drop Photos Here to Upload

##### drag-and-drop-upload.js

一样

提交到github

$ cd /root/suyn_website

# 因为Git是分布式版本控制系统,所以每个机器都必须自报家门:你的名字和Email地址。

$ git config --global user.name "Your Name"

$ git config --global user.email "email@example.com"

$ git init #把当前目录变成Git可以管理的仓库,生成的.git目录(Git的版本库),是Git来跟踪管理版本库的。

$ git add uploadFiles/ #把xx添加到仓库

## 跳到uploadFiles目录里执行以下命令:

$ git commit -m "first commit to my github" #把xx提交到仓库

## Before below:在GitHub创建同名空仓库

$ git remote add origin git@github.com:userName/uploadFiles.git

# 把当前分支master(默认)推送到远程,远程库的名字就是origin(默认)

$ git push -u origin master

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值