• django文件上传


    当django处理文件上传时,文件数据被打包封装在request.FILES中

    1、基本文件上传

    首先写一个form表单,它必须包含一个FileField文件字段:

    #forms.py
    
    from django import forms
    
    class UploadFileForm(forms.Form):
        title = forms.CharField(max_length=50)
        file = forms.FileField()

    处理这个表单的视图将在request.FILES中收到文件数据,可以用request.FILES['file']来获取上传文件的具体数据,其中的键值'file'是根据form表单中字段file=forms.FileField()的变量名来的

    注意:request.FILES只有在请求方法为POST,并且提交请求的<form>具有enctype="multipart/form-data"属性时才有效,否则request.FILES将为空

    下面是一个接收上传文件的视图范例:

    #views.py
    
    from django.http import HttpResponse
    from django.shortcuts import render
    from .forms import UploadFileForm
    from django.conf import settings
    
    #创建函数处理上传文件数据
    def handle_uploaded_file(f,filename):
        filename_path = f'{settings.MEDIA_ROOT}{filename}'  #生成文件名及路径
        with open(filename_path,'wb+') as destination:
            for chunk in f.chunks():
                destination.write(chunk)
            destination.close()
    
    def index(request):
        if request.method == 'POST':
            forms = UploadFileForm(request.POST,request.FILES)
            if forms.is_valid():
                handle_uploaded_file(request.FILES['file'],filename=request.FILES.get('file'))
                return HttpResponse('file for upload ok')
            print(forms)
    
        else:
            forms = UploadFileForm()
            print(forms)
        return render(request,'index.html',context={'forms':forms})

    在文件上传期间,实际文件数据存储在request.FILES,此字典中的每个条目都是一个UploadedFile对象,此对象包括以下方法和属性:

    UploadedFile.read():从文件中读取整个上传的数据,小心这个方法,如果上传的文件太大,如果你试图将它读入内存,它会消耗系统大量内存,你可以使用cunks()方法

    UploadedFile.multipls_chunks(chunk_size=None):如果上传的文件足够大,需要在多个块中读取,则返回True,默认为True,默认chunk_size为2.5M,也可以指定

     UploadedFile.chunks(chunk_size=None):生成器返回文件的块,如果multiple_chunks()为True,则因该尽量使用此方法而不是read()方法,在实践中通常最简单的方法就是一直使用chunks(),通过循环chunks()来存储文件数据

    UploadedFile长用的一些属性:

    UploadedFile.name:上传文件的名称

    UploadedFile.size:上传文件大小

    UploadedFile.content_type:随文件一起上传的内容类型标题(如:text/plain或application/pdf)

    UploadedFile.content_type_extra:包含传递给content-type标头的额外参数的字典

    UploadedFile.charset:队友text/content-types提供的utf8字符集编码

    其它文件代码:

    #urls.py
    from django.contrib import admin
    from django.urls import path,re_path
    from testfileile import views
    
    urlpatterns = [
        path('admin/', admin.site.urls),
        re_path(r'^$',views.index,name='index'),
    
    
    #settings.py配置媒体文件上传目录和访问路径
    MEDIA_ROOT = os.path.join(BASE_DIR,'static/images/')
    MEDIA_URL = '/media/'
    
    #index.html
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>index</title>
    </head>
    <body>
    <form method="post" action="/" enctype="multipart/form-data"> #上传文件时必须包含enctype属性
        {% csrf_token %}
        {{ forms }}<br>
        <input type="submit" value="提交">
    </form>
    </body>
    </html>

    2、使用模型处理上传的文件

    如果是通过模型层的model来指定上传文件的保存方式,使用ModelForm更方便,调用form.save()的时候,文件对象会保存在相应的FileField的upload_to参数指定的地方,实际文件会存储在settings配置文件中MEDIA_ROOT指定的绝对路径加upload_to子目录下

    看如下示例:

    #models.py
    
    from django.db import models
    
    
    class ModelFileField(models.Model):
        title = models.CharField(max_length=200)
        file = models.FileField(upload_to='photos/%Y/%m/%d') #将格式化为时间目录
    
    #froms.py通过模型创建表单
    
    from .models import ModelFileField
    from django.forms import ModelForm
    
    class ModelFormFile(ModelForm):
        class Meta:
            model = ModelFileField
            fields = "__all__"
    
    #views.py
    
    from django.http import HttpResponse
    from django.shortcuts import render
    from .forms import ModelFormFile
    
    def upload_file(request):
        if request.method == 'POST':
            forms = ModelFormFile(request.POST,request.FILES)
            if forms.is_valid():
                forms.save(commit=True) #文件直接保存在model中的upload_to指定的子目录下
                return HttpResponse('ok')
        else:
            forms = ModelFormFile()
        return render(request,'upload.html',{'forms':forms})
    
    #settings.py
    MEDIA_ROOT = os.path.join(BASE_DIR,'static/images/')
    MEDIA_URL = '/media/'
    
    #upload.html
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>upload file</title>
    </head>
    <body>
    <form method="post" action="{% url 'upload' %}" enctype="multipart/form-data">
        {% csrf_token %}
        {{ forms }}<br>
        <input type="submit" value="提交">
    </form>
    </body>
    </html>

    如果要手动指定对象,只需将文件对象request.FILES赋值给模型中的文件字段即可:

    但需要注意,如有其它字段必须允许为空,否则将引发异常!

    #views.py
    
    from django.http import HttpResponse
    from django.shortcuts import render
    from .forms import ModelFormFile
    from .models import ModelFileField
    
    def upload_file(request):
        if request.method == 'POST':
            forms = ModelFormFile(request.POST,request.FILES)
            if forms.is_valid():
                instance = ModelFileField(file=request.FILES['file']) #将文件数据指定到模型字段
                instance.save()
                #forms.save(commit=True)
                return HttpResponse('ok')
        else:
            forms = ModelFormFile()
        return render(request,'upload.html',{'forms':forms})

    3、同时上传多个文件

    如果要使用一个表单字段同时上传多个文件,需设置字段HTML标签的mulpiple属性为True,在django表单中设置小部件HTML的属性:

    #forms.py
    
    from django import forms
    from .models import ModelFileField
    from django.forms import ModelForm
    
    class ModelFormFile(ModelForm):
        class Meta:
            model = ModelFileField
            fields = "__all__"
            widgets = {
                'file':forms.ClearableFileInput(attrs={'multiple':True})
            } #上面模型的基础上,创建的forms表单添加HTML属性multiple

    在视图中存储多个文件则需要通过getlist方法获取多个文件的列表,然后循环存储到数据并保存即可:

    #views.py
    
    from django.http import HttpResponse
    from django.shortcuts import render
    from .forms import ModelFormFile
    from .models import ModelFileField
    
    def upload_file(request):
        if request.method == 'POST':
            forms = ModelFormFile(request.POST,request.FILES)
            if forms.is_valid():
                for i in request.FILES.getlist('file'): #获取文件列表
                    instance = ModelFileField(file=i)
                    instance.save()
                return HttpResponse('ok')
        else:
            forms = ModelFormFile()
        return render(request,'upload.html',{'forms':forms})

    4、上传文件处理器

    当用户上传一个文件的时候,Django会把文件数据传递给上传文件处理器一个类。

    上传处理器的配置定义在FILE_UPLOAD_HANDLERS中,默认为:

    ["django.core.files.uploadhandler.MemoryFileUploadHandler", "django.core.files.uploadhandler.TemporaryFileUploadHandler"]

    MemoryFileUploadHandler和TemporaryFileUploadHandler定义了Django的默认文件上传行为:将小文件读取到内存中,大文件放置在磁盘中。

    在你保存上传文件之前,数据需要储存在某个地方。通常,如果上传文件小于2.5MB,Django会把整个内容存到内存。 这意味着,文件的保存仅仅涉及到内存中的读取和磁盘的写入,所以非常快。但是,如果上传的文件很大,Django会把它写入一个临时文件,储存在你的系统临时目录中。在类Unix的平台下,Django会生成一个文件,名称类似于/tmp/tmpzfp6I6.upload。

    我们可以编写自定义的处理器,来定制Django如何处理文件。例如,根据级别不同限制用户的磁盘配额,在运行中压缩数据,渲染进度条,甚至是转存到另一个储存位置,而不把它存到本地。

  • 相关阅读:
    Tree(未解决。。。)
    Fractal(递归,好题)
    Scrambled Polygon(凸多边形,斜率)
    ZYB's Game(博弈)
    Dancing Stars on Me(判断正多边形)
    Hidden String(深搜)
    1043
    TEX Quotes(字符串,水)
    Candy Sharing Game(模拟搜索)
    hpu校赛--雪人的高度(离散化线段树)
  • 原文地址:https://www.cnblogs.com/zhangxinqi/p/10785351.html
Copyright © 2020-2023  润新知