file上传代码 ios_[Django]Web app开发随记----文件上传篇

d16886f0cf9d943497f65924d4014dea.png

昨晚一股劲上头弄到了凌晨1点,今早到了公司才想起来代码还没传到Github上,果然人太困了做啥都是丢三落四的,今晚回家得赶紧备份上。

这次做的内容相对于之前的内容来说算是一次大更新,在我还没忘记之前得赶紧记下来。除了文件上传,还有输入框的调整也花了很多心思,有时间还得再开一篇接着写。

首先,说一下自己的操作环境: Django 2.2, Python 3.5

理解一下Django的文件传输步骤:

  1. 本地用户在网页的表单选择文件
  2. 被选择的文件会以非加工处理的方式传至服务器
  3. 在服务器端生成TemporaryUploadedFile形式的数据(储存在类似于/tmp/tmpzfp6I6.upload的位置,此时可以对数据进行加工)
  4. 最后TUF形式的数据被转换成实体数据存放在指定位置

这次我是没有在Model文件里添加ImageField,这样做的原因一个是节省数据库的空间,不想破坏现有的结构,另一个就是一个帖子对应多个图片,不知道ImageField支不支持链接多个图片。不过这样的操作是不推荐的,因为要控制用户上传的文件类型什么的就很麻烦,还在找更好的方法,如果有好方法也欢迎留言讨论。

接着就是代码。很多教程里面都提到了在setting.py里面添加[MEDIA_ROOT="media"]的步骤,但如果你没有在Model.py里面加FileField,或者不方便加,其实可以省掉改Setting.py文件的这个步骤。

这样,直接在Form.py里面添加:

from django import forms

class UploadFileForm(forms.Form):
    File_upload = forms.FileField()

但这个只能上传一个文件,想要上传多个文件的话,可以这么写:

from django import forms

class UploadFileForm(forms.Form):
    File_upload = forms.FileField(widget=forms.ClearableFileInput(attrs={'multiple': True}))

括号里面添加的 multiple 就是允许上传条上传多个文件的属性。

然后在html里加入表单:

<form enctype="multipart/form-data" method="post" action="文件上传位置">
    {{ form.File_upload }}<!--可以对表格随意更改,比如用django-widget-tweaks什么的-->
</form>

这样一个基本的文件上传条就加好了。如果要自定义文件储存位置的话action可以省略,后面我们自己处理。要注意的是 enctypemethod 两个属性不可缺少,不然文件无法跟表格绑定,提交表格的时候文件无法一起提交上去。

在Django模型组里面,ImageField属于FileField系列,所以想要上传图片的时候可以直接把FileField替换成ImageField。

如果我们做的是一个表格组,除了上传文件之外还有别的表单数据的话,可以把这两个属性加在html里最外面的Form属性上,比如:

<form enctype="multipart/form-data" method="post" action="文件上传位置">     
    {{for field in form}}<!--用form.py做个集合-->
    ....
    {{ endfor }}
</form>

然后接下来就是对View.py文件的修改,先贴一段Django官方的代码,然后我慢慢解释:

from .forms import UploadFileForm

def upload_file(request):
    if request.method == 'POST':
        form = UploadFileForm(request.POST, request.FILES) # 比起平常的提交表格多了request.FILES
        if form.is_valid():
            handle_uploaded_file(request.FILES['file']) # 这个位置可以替换成别的写法
            return HttpResponseRedirect('/success/url/')
    else:
        form = UploadFileForm()
    return render(request, 'upload.html', {'form': form})

# 这段是后面要讲到的
def handle_uploaded_file(f):
    with open('some/file/name.txt', 'wb+') as destination:
        for chunk in f.chunks():
            destination.write(chunk)

用Django做过普通Form的人对

form = UploadFileForm(request.POST, request.FILES)

这句很眼熟,因为一般表单的数据都这么处理:

form = UploadFileForm(request.POST)

后面加上 request.FILES 就成了上传文件时用到的格式 ,至于要将文件保存下来,则需要 write 或 save 函数。

也就是

handle_uploaded_file(request.FILES['file']) # 这个位置可以替换成别的写法

可以写成

request.FILES['file'].save()

这样上传的文件会直接储存到你指定的位置。但直接这样写会有一个缺点,那就是当文件比较大的时候,特别占用服务器的内存(参照传输步骤的第三步,服务器会生成一个临时文件),尤其是当你架构一个网站,有那么多人同时上传文件的话,说不定服务器内存不够就直接down了。

所以这时候上传文件的Handle就派上了用场。

以官网的代码为例:

def handle_uploaded_file(f):
    with open('some/file/name.txt', 'wb+') as destination:
        for chunk in f.chunks():
            destination.write(chunk)

这个函数就是上传文件的Handle函数,这个函数里面将一个file分解成了chunk。可以想象成一把刀把一个大文件切成了小块,然后一块一块的写入储存。Django提供了很好的扩展性,我们可以自己定义这个chunk的大小(一个chunk的初始值为64KB)

(接下来慢慢补充对于上传文件Handle的处理,etc)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值