新乡做网站的,电子商务有哪些工作岗位,网站访问量大 处理,浦城 网站 做## Django文件上传需要考虑的重要事项 文件或图片一般通过表单进行。用户在前端点击文件上传#xff0c;然后以POST方式将数据和文件提交到服务器。服务器在接收到POST请求后需要将其存储在服务器上的某个地方。Django默认的存储地址是相对于根目录的/media/文件夹…## 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_rootsettings.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_touser_directory_path, nullTrue) upload_method models.CharField(max_length20, verbose_nameUpload 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, namefile_upload), # Upload Files Using Model Form re_path(r^upload2/$, views.model_form_upload, namemodel_form_upload), # View File List path(file/, views.file_list, namefile_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(widgetforms.ClearableFileInput(attrs{class: form-control})) upload_method forms.CharField(labelUpload Method, max_length20, widgetforms.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 methodpost enctypemultipart/form-data {% csrf_token %} {{ form.as_p }} button classbtn btn-info form-control typesubmit valuesubmitUpload/button /form {% endblock %} 显示文件清单模板file_list.html代码如下所示:
html # file_upload/templates/file_list.html {% extends file_upload/base.html %}
{% block content %} h3File 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 classtable table-striped tbody tr tdFilename URL/td tdFilesize/td tdUpload Method/td /tr {% for file in files %} tr tda 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 %}
pNo 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可以将文件大小显示为人们可读的方式如MBKB。
## 使用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} )