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文件上传下载与富文本编辑框的更多相关文章

  1. django文件上传下载

    views: def mgmt_files(request): #列出树形目录,上传文件页面 if request.method == 'POST': path_root = "D:\\py ...

  2. django 12天(跨域,文件上传,下载,cookie,session)

    django 12天(跨域,文件上传,下载) 跨域 什么是跨域 1.协议不同 2.端口不同 3.主机不同 如何解决跨域 1.安装django-cors-headers模块 2.在settings.py ...

  3. java中的文件上传下载

    java中文件上传下载原理 学习内容 文件上传下载原理 底层代码实现文件上传下载 SmartUpload组件 Struts2实现文件上传下载 富文本编辑器文件上传下载 扩展及延伸 学习本门课程需要掌握 ...

  4. Struts的文件上传下载

    Struts的文件上传下载 1.文件上传 Struts2的文件上传也是使用fileUpload的组件,这个组默认是集合在框架里面的.且是使用拦截器:<interceptor name=" ...

  5. Android okHttp网络请求之文件上传下载

    前言: 前面介绍了基于okHttp的get.post基本使用(http://www.cnblogs.com/whoislcj/p/5526431.html),今天来实现一下基于okHttp的文件上传. ...

  6. Selenium2学习-039-WebUI自动化实战实例-文件上传下载

    通常在 WebUI 自动化测试过程中必然会涉及到文件上传的自动化测试需求,而开发在进行相应的技术实现是不同的,粗略可划分为两类:input标签类(类型为file)和非input标签类(例如:div.a ...

  7. 艺萌文件上传下载及自动更新系统(基于networkComms开源TCP通信框架)

    1.艺萌文件上传下载及自动更新系统,基于Winform技术,采用CS架构,开发工具为vs2010,.net2.0版本(可以很容易升级为3.5和4.0版本)开发语言c#. 本系统主要帮助客户学习基于TC ...

  8. 艺萌TCP文件上传下载及自动更新系统介绍(TCP文件传输)(一)

    艺萌TCP文件上传下载及自动更新系统介绍(TCP文件传输) 该系统基于开源的networkComms通讯框架,此通讯框架以前是收费的,目前已经免费并开元,作者是英国的,开发时间5年多,框架很稳定. 项 ...

  9. ssh框架文件上传下载

    <!doctype html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

随机推荐

  1. JSP2的自定义标签和方法

    Jsp2的自定义标签 Jsp2 开发标签库的几个步骤: 开发自定义标签处理类. 建立一个*.tld文件,每个tld文件对应一个标签库,每个标签库可对应多个标签. 在jsp文件中使用自定义标签 空标签 ...

  2. paste - 合并文件各行

    总览 (SYNOPSIS) ../src/paste [OPTION]... [FILE]... 描述 (DESCRIPTION) 连续 依次 从 各个 文件 FILE 中 读取 一行 然后 合并成 ...

  3. 零点.Net Core 接触

    一.Program.cs类与Startup类 1.一切从Main开始,Main方法包含了是整个应用程序的入口 ASP.NET Core应用程序可以配置和启动主机(Host). 主机负责应用程序启动和生 ...

  4. Read-Only Tables 只读表

    Put  a table into read-only  mode,which prevents DDL or DML changes during table maintenance Put the ...

  5. Jmeter接口测试---加解密

    1.加解密的jar包放到jmeter的lib/ext目录下. 项目打jar包参考https://www.cnblogs.com/fulucky/p/9436229.html 2.在测试计划---> ...

  6. MacOS系統Flutter打包apk

    一.打包前需要做一些基本设置的确认 1.应用名 2.权限设置 3.applicationId:应用唯一标识符 4.versionCode:版本号 5.versionName:版本名称 6.APP应用图 ...

  7. Test 6.23 T1 扫雷

    题目背景 题目描述 输入格式 输出格式 样例输入输出 数据范围 解析 我们设两个作弊器的参数分别为\((a_1,b_1)\)和\((a_2,b_2)\),那么设 \[ S1=\frac{a_1}{b_ ...

  8. hdu 6152 : Friend-Graph (2017 CCPC网络赛 1003)

    题目链接 裸的结论题.百度 Ramsey定理.刚学过之后以为在哪也不会用到23333333333,没想到今天网络赛居然出了.顺利在题面更改前A掉~~~(我觉得要不是我开机慢+编译慢+中间暂时死机,我还 ...

  9. web页面上传大文件有没有好的解决方案

    本人在2010年时使用swfupload为核心进行文件的批量上传的解决方案.见文章:WEB版一次选择多个文件进行批量上传(swfupload)的解决方案. 本人在2013年时使用plupload为核心 ...

  10. hibernate插入中文字段时,无法插入数据库

    体现: hibernate插入数据时,一直报错: Caused by: java.sql.SQLException: Incorrect string value: '\xE5\xBC\xA0\xE4 ...