Django文件上传下载与富文本编辑框
django文件上传下载
上传
配置settings.py
# 设定文件的访问路径,如:访问http://127.0.0.1:8000/media/就可以获取文件
MEDIA_URL = '/media/'
# 设置文件的存储路径,全部存储在media目录下,会和model类中的upload_to属性值拼接
MEDIA_ROOT = os.path.join(BASE_DIR,'media')
models.py
class Img(models.Model):
name = models.CharField(max_length=32)
# upload_to拼接在MEDIA_ROOT后面,../media/img/article/,内容均存在该目录下
img = models.ImageField(upload_to='img/article/',verbose_name='图片')
upload.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<!--enctype属性值修改成"multipart/form-data"-->
<form action="" method="post" enctype="multipart/form-data">
{% csrf_token %}
<!--type类型要改成file,文件类型-->
<input type="text" name="name">
<input type="file" name="img">
<button>上传</button>
</form>
</body>
</html>
<!--多文件上传-->
<input type="file" name="myfiles" multiple="">
views.py
# 获取上传文件单个插入数据
def upload(request):
if request.method == 'POST':
# 获取文件名称
img_url = request.FILES.get("img")
name = request.POST.get("name")
# 存到数据库中,并保存到指定的目录下
img = models.Media(name=name,img=img_url)
img.save()
return render(request,"youhua.html")
# 获取上传文件插入批量数据
def upload(request):
if request.method == 'POST':
img_list = request.FILES.getlist('img')
name = request.POST.get("name")
querysetlist = []
for img in img_list:
querysetlist.append(models.Media(name=name,img=img))
models.Media.objects.bulk_create(querysetlist)
return HttpResponse("上传成功")
return render(request, "youhua.html")
ajax上传图片
FormData上传
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="https://cdn.staticfile.org/jquery/1.10.2/jquery.min.js"></script>
</head>
<body>
<input type="file" name="img" id="img">
<input type="button" value="上传" onclick="showImg();">
<script type="text/javascript">
function showImg() {
var formdata = new FormData();// 创建一个空的FormData对象,可以使用formdata.append(key,value)来添加数据。
formdata.append('file', document.getElementById('img').files[0]);
$.ajax({
url: '/upload/',
type: 'post',
headers :{
'x-csrftoken': '{{ csrf_token }}', // 为了通过csrf校验,所以必须带这个过去。
},
data: formdata,
// 默认值为true,默认会将发送的数据序列化以适应默认的内容类型。不想转换信息,需要设置为false
// 此数据传输的是对象,所以不需要序列化
processData: false,
// 不写默认为application/x-www-form-urlencoded只能上传文本,上传文件需要用multipart/form-data类型。
contentType: false, // 不设置内容类型
success: function (data) {
alert(data)
}
});
}
</script>
</body>
</html>
views.py
def upload(request):
if request.method == 'POST':
img_url = request.FILES.get('file')
img = models.Media(name='hello',img=img_url)
img.save()
ret = '上传成功'
return HttpResponse(ret)
return render(request,"youhua.html")
页面展示图片
如果涉及到下载/显示资源,就需要添加url
from django.contrib import admin
from django.urls import path
from imgTest.views import uploadImg, showImg
from django.conf.urls.static import static
from django.conf import settings
# 写法一
urlpatterns = [
path('admin/', admin.site.urls),
path('upload/', upload),
path('showImg/', showImg)
] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
# 写法二
from django.views.static import serve
urlpatterns = [
...
path('showImg/', showImg),
url('^media/(?P<path>.*)', serve, {'document_root': settings.MEDIA_ROOT})
]
views.py
def showImg(request):
obj_list = models.Img.objects.all()
print(obj_list)
return render(request,'showImg.html',{"obj_list":obj_list})
showImg.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
{% for obj in obj_list %}
<!--必须要带url,不然路径会错误-->
<img src="{{ obj.img.url }}" alt="">
{% endfor %}
</body>
</html>
文件下载
自定义编写视图下载方法,主要是为了限制用户的下载内容,一定要注意限制用户的下载内容,不然知道路径连代码和数据库都下载了。
urls.py
from app_youhua import views
urlpatterns = [
# ......
url('^download/(?P<pk>\d+)/$', views.download, name='download'),
]
html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
{% load static %}
</head>
<body>
{% for obj in obj_list %}
<img src="{{ obj.img.url }}" alt=""> <!--自动将数据库中的图片全部显示,可以自定制拼接路径-->
<a href="{% url 'download' obj.pk %}">下载</a> <!--url反向解析-->
{% endfor %}
</body>
</html>
使用HttpResponse
from django.http import HttpResponse, Http404
def download(request, pk=None):
obj = models.Media.objects.get(pk=pk)
filename = str(obj.img)
filepath = os.path.join(settings.MEDIA_ROOT, filename)
with open(filepath, 'rb') as f:
try:
response = HttpResponse(f)
response['content_type'] = "application/octet-stream"
response['Content-Disposition'] = 'attachment; filename=%s' % filename
return response
except Exception:
raise Http404
HttpResponse有个很大的弊端,其工作原理是先读取文件,载入内存,然后再输出。如果下载文件很大,该方法会占用很多内存。对于下载大文件,Django更推荐StreamingHttpResponse和FileResponse方法,这两个方法将下载文件分批(Chunks)写入用户本地磁盘,先不将它们载入服务器内存。
使用StreamingHttpResponse和FileResponse
from django.http import FileResponse, StreamingHttpResponse
def download(request, pk=None):
obj = models.Media.objects.get(pk=pk)
filename = str(obj.img)
# filename = request.GET.get('file') # 如果文件名直接通过页面传回
filepath = os.path.join(settings.MEDIA_ROOT, filename)
# 文件将会自动关闭,所以不需要使用with语句打开文件
fp = open(filepath, 'rb')
response = StreamingHttpResponse(fp)
# response = FileResponse(fp) # 默认一次下载4096字节
response['Content-Type'] = 'application/octet-stream'
response['Content-Disposition'] = 'attachment;filename="%s"' % filename
return response
文件私有化的两种方法
如果你想实现只有登录过的用户才能查看和下载某些文件。
上传文件放在media文件夹,文件名使用很长的随机字符串命名(uuid), 让用户无法根据文件名猜出这是什么文件。视图和模板里验证用户是否已登录,登录或通过权限验证后才显示具体的url。- 简单易实现,安全性不高,但对于一般项目已足够。
上传文件放在非media文件夹,用户即使知道了具体文件地址也无法访问,因为Django只会给media文件夹里每个文件创建独立url资源。视图和模板里验证用户是否已登录,登录或通过权限验证后通过自己编写的下载方法下载文件。- 安全性高,但实现相对复杂。
我们定义的下载方法可以下载所有文件,不仅包括.py文件,还包括不在media文件夹里的文件(比如非用户上传的文件)。比如当我们直接访问127.0.0.1:8000/file/download/file_project/settings.py/时,你会发现我们连file_project目录下的settings.py都下载了。
# 简单举例,不让用户下载.py等结尾的文件
from django.http import Http404,FileResponse, StreamingHttpResponse
def download(request, pk=None):
obj = models.Media.objects.get(pk=pk)
filename = str(obj.img)
filepath = os.path.join(settings.MEDIA_ROOT, filename)
ext = os.path.basename(file_path).split('.')[-1].lower()
# cannot be used to download py, db and sqlite3 files.
if ext not in ['py', 'db', 'sqlite3']:
# 文件将会自动关闭,所以不需要使用with语句打开文件
fp = open(filepath, 'rb')
response = StreamingHttpResponse(fp)
response['content_type'] = "application/octet-stream"
response['Content-Disposition'] = 'attachment;filename="%s"' % filename
return response
else:
raise Http404
django富文本编辑框
下载
pip install django-ckeditor
注册
INSTALLED_APPS = [
...
'ckeditor',
'ckeditor_uploader',
]
settings中配置
CKEDITOR_UPLOAD_PATH = 'ckeditor/'
配置urls.py
from ckeditor_uploader import views
from django.views.static import serve
urlpatterns = [
url(r'^media/(?P<path>.*)', serve, {'document_root':settings.MEDIA_ROOT}),
# 上传文件
url(r'^ckeditor/upload/', views.upload),
url(r'^ckeditor/', include('ckeditor_uploader.urls')),
]
models.py使用富文本编辑框字段
from ckeditor_uploader.fields import RichTextUploadingField
class Article(models.Model):
title = models.CharField(max_length=32)
detail = models.OneToOneField('ArticleDetail',on_delete=models.CASCADE)
class ArticleDetail(models.Model):
content = RichTextUploadingField(verbose_name='文章详情')
模板中使用
{{ field }} 使用ModelForm富文本编辑框的字段,
# 导入js样式,只要需要显示富文本编辑框就要导入
<script src="{% static 'ckeditor/ckeditor/ckeditor.js' %}"></script>
<script src="{% static 'ckeditor/ckeditor-init.js' %}"></script>
关联表同时显示富文本编辑框
比如:编辑内容时,肯定是连同关联的详情内容一同填写。
# 视图函数
def article_add(request):
# 对两个form表单进行实例化
form_obj = ArticleForm()
detail_form = ArticleDetailForm()
if request.method == 'POST':
# 先校验并保存被关联方
detail_form = ArticleDetailForm(request.POST)
if detail_form.is_valid():
detail_form.save()
qd = request.POST.copy() # request.POST是有序字典,默认是不可编辑,所以进行深拷贝后编辑
# 找到被关联方提交此条数据的pk
qd['detail'] = detail_form.instance.pk
# 校验并保存被关联方
form_obj = ArticleForm(data=qd, files=request.FILES) # 如存在文件类,需单独传参
if form_obj.is_valid():
form_obj.save()
return redirect(reverse('backend:article_list'))
# 如果被关联方未通过校验,且关联方通过校验并保存,则删除关联方保存的数据
if detail_form.is_valid() and detail_form.instance:
detail_form.instance.delete()
title = '新增文章'
return
render(request,'backend/article_form.html'{'form_obj':form_obj,'title':title,'detail_form':detail_form})
from django import forms
from repository import models
class ArticleForm(forms.ModelForm):
class Meta:
model = models.Article
fields = '__all__'
def __init__(self,*args,**kwargs):
super(ArticleForm, self).__init__(*args,**kwargs)
for field in self.fields.values():
# 用来控制不使用'form-control'样式的
if isinstance(field.widget,forms.ClearableFileInput):
continue
field.widget.attrs['class'] = 'form-control'
class ArticleDetailForm(forms.ModelForm):
class Meta:
model = models.ArticleDetail
fields = '__all__'
Django文件上传下载与富文本编辑框的更多相关文章
- django文件上传下载
views: def mgmt_files(request): #列出树形目录,上传文件页面 if request.method == 'POST': path_root = "D:\\py ...
- django 12天(跨域,文件上传,下载,cookie,session)
django 12天(跨域,文件上传,下载) 跨域 什么是跨域 1.协议不同 2.端口不同 3.主机不同 如何解决跨域 1.安装django-cors-headers模块 2.在settings.py ...
- java中的文件上传下载
java中文件上传下载原理 学习内容 文件上传下载原理 底层代码实现文件上传下载 SmartUpload组件 Struts2实现文件上传下载 富文本编辑器文件上传下载 扩展及延伸 学习本门课程需要掌握 ...
- Struts的文件上传下载
Struts的文件上传下载 1.文件上传 Struts2的文件上传也是使用fileUpload的组件,这个组默认是集合在框架里面的.且是使用拦截器:<interceptor name=" ...
- Android okHttp网络请求之文件上传下载
前言: 前面介绍了基于okHttp的get.post基本使用(http://www.cnblogs.com/whoislcj/p/5526431.html),今天来实现一下基于okHttp的文件上传. ...
- Selenium2学习-039-WebUI自动化实战实例-文件上传下载
通常在 WebUI 自动化测试过程中必然会涉及到文件上传的自动化测试需求,而开发在进行相应的技术实现是不同的,粗略可划分为两类:input标签类(类型为file)和非input标签类(例如:div.a ...
- 艺萌文件上传下载及自动更新系统(基于networkComms开源TCP通信框架)
1.艺萌文件上传下载及自动更新系统,基于Winform技术,采用CS架构,开发工具为vs2010,.net2.0版本(可以很容易升级为3.5和4.0版本)开发语言c#. 本系统主要帮助客户学习基于TC ...
- 艺萌TCP文件上传下载及自动更新系统介绍(TCP文件传输)(一)
艺萌TCP文件上传下载及自动更新系统介绍(TCP文件传输) 该系统基于开源的networkComms通讯框架,此通讯框架以前是收费的,目前已经免费并开元,作者是英国的,开发时间5年多,框架很稳定. 项 ...
- ssh框架文件上传下载
<!doctype html> <html lang="en"> <head> <meta charset="UTF-8&quo ...
随机推荐
- 如何同步发送put或者delete请求
1.必须把前端发送方式改为post . 2.在web.xml中配置一个filter:HiddenHttpMethodFilter过滤器 3.必须携带一个键值对,key=_method, value= ...
- 关于windows服务器配置
#我是用的window service2008系统,在配置服务器时由于是用php进行搭建 #首先我安装好phpstudy,通过服务器ip访问,显示了个helloworld,我查看了phpstudy里的 ...
- HDU 5386 Cover
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5386 题目大意:给一个初始矩阵(n×n).一个目标矩阵(n×n)和m个操作,要求找到一种操作顺序,使初 ...
- Ubuntu 18.04 安装 CUDA 9.0
sudo dpkg -i cuda-repo-ubuntu1604-9-0-local_9.0.176-1_amd64.deb sudo apt-key add /var/cuda-repo-< ...
- OC中保存自定义类型对象的持久化方法
OC中如果要将自定义类型的对象保存到文件中,必须进行以下三个条件: 想要把存放自定义类型的数组进行 持久化(就是将内存中的临时数据以文件<数据库等>的形式写到磁盘上)必须满足: 1. 自定 ...
- 转载-使用Nodepad++来编辑我们服务器的配置文件
转自------------------ 作者:李阿昀 来源:CSDN 原文:https://blog.csdn.net/yerenyuan_pku/article/details/73128819 ...
- Eclipse使用maven创建SSM-web项目
1.环境准备 (1)maven:apache-maven-3.5.2,我的maven安装在D:\apache-maven-3.5.2,eclipse中maven配置如下: 先add ,添加好自己的ma ...
- css3新增的属性 - 分享
CSS3新增属性 一.transform变换效果 CSS3 提供了元素变形效果,也叫做变换.它可以将元素实现旋转.缩放和平移的功能. 属性有两个:transform 和 transform-ori ...
- FastDFS搭建文件管理系统
参考:https://www.cnblogs.com/chiangchou/p/fastdfs.html 目录: 一:FastDFS介绍 1:简介: FastDFS 是一个开源的高性能分布式文件系统( ...
- 回归平方和 ESS,残差平方和 RSS,总体平方和 TSS
https://zhidao.baidu.com/question/565190261749684764.html 回归平方和 ESS,残差平方和 RSS,总体平方和 TSS 总变差 ...