django文件上传

34 篇文章 0 订阅
9 篇文章 0 订阅

文件上传

一、概要

文件上传与下载也是开发中的比较重要的功能

二、前期配置文件

  1. 在settings文件中
    MEDIA_ROOT = BASE_DIR + ‘/media/’
    BASE_DIR 是项目所在的目录,这样文件就会存储在当前的开发目录下的一个media的文件夹下
    MEDIA_URL = ‘/media/’
  2. 在整个项目中添加的url.py中
    urlpatterns = [
    url(r’^admin/’, admin.site.urls),
    ] + static(settings.MEDIA_URL,document_root=settings.MEDIA_ROOT)
    #官方给出的在开发中显示图片的方式,但是只能用于本地开发的时候,也就是127.0.0.1的时候。而不能用在发布版

三、相关类

1、说明

  1. 表单上传的文件对象存储在类字典对象request.FILES中,表单格式需为multipart/form-data
  2. request.FILES中的键来自于表单中的的name值:
  3. request.FILES中的值均为UploadedFile类文件对象。

2、request.FILES

  1. 说明
    一个类字典对象,包含所有上传的文件。 FILES 的键来自 中的 name。 FILES 的值是一个标准的Python字典
  2. 示例代码
    # 返回 uploadfile对象 key对应的是input对象的name的值, 默认是file
    upload_file =request.FILES[‘file’]
    #或者
    upload_file =request.FILES.get(‘file’)
  3. 返回值
    QueryDict对象
  4. 注意
    FILES 只在请求的方法是 POST,并且提交的 包含enctype="multipart/form-data"时才包含数据。否则, FILES 只是一个空的类字典对象。

3、UploadedFile

  1. 说明
    是类文件对象
  2. 方法
    • UploadedFile.read()
      读取整个上传文件的数据,文件较大时慎用。
    • UploadedFile.multiple_chunks(chunk_size=None)
      判断文件是否足够大,一般为设置2.5M
    • UploadedFile.multiple_chunks(chunk_size=None)
      返回一个生成器对象,当multiple_chunks()为True时应该使用这个方法来代替read()
    • UploadedFile.chunks(chunk_size=None)
      返回一个生成器对象指定切割文件大小
    • UploadedFile.name
      上传文件的name。
    • UploadedFile.size
      上传文件的大小
    • UploadedFile.content_type
      上传文件时的content_type报头,例如(image/* , application/pdf).
    • UpladedFile.charset
      获取上传文件的编码

四、文件上传

1、说明

表单上传的文件对象存储在类字典对象request.FILES中,表单格式需为multipart/form-data

2、示例代码

  1. 前端

    <form enctype="multipart/form-data" method="post" action="/upload">
    	<input type="file" name="head" />
    </form>  
    
  2. views

    def upload(request):
        if request.method == 'POST':
            username = request.POST.get('username')
            password = request.POST.get('password')
            user = UserInfo()
            user.head = request.FILES.get('head')
            user.username = username
            user.password = password
            user.save()
        return render(request, 'index.html')
    
  3. models

    class UserInfo(models.Model):
        uid = models.AutoField(primary_key=True)
        username = models.CharField(max_length=32, unique=True)
        password = models.CharField(max_length=32)
        # "直接定位到media目录下"
        #
        head = models.FileField(upload_to='account/user/%Y%m%d')
        class Meta:
        	db_table = 'T_USER_INFO'
    
  4. 如果需要给文件重名了,定义一个类继承FileSystemStorage 重新_save()方法

    from django.core.files.storage import FileSystemStorage

    class CustomFileStorage(FileSystemStorage):
        from django.conf import settings
        def __init__(self, location=settings.MEDIA_ROOT, base_url=settings.MEDIA_URL):
            # 初始化
            super(ImageStorage, self).__init__(location, base_url)
    
        # 重写 _save方法
        def _save(self, name, content):
            # name为上传文件名称
            import os, time, random
            # 文件扩展名
            ext = os.path.splitext(name)[1]
            # 文件目录
            d = os.path.dirname(name)
            # 定义文件名,年月日时分秒随机数
            fn = time.strftime('%Y%m%d%H%M%S')
            fn = 'IMG_' + fn + '%d' % random.randint(0, 100)
            # 重写合成文件名
            name = os.path.join(d, fn + ext)
            # 调用父类方法
            return super()._save(name, content)
    #在models中添加
    # 如果上传文件可以将ImageField换为FileField
    pic=models.ImageField(upload_to='img/%Y/%m/%d',storage=CustomFileStorage())  
    

五、自带的Form来处理上传文件

  1. 定义models

    class UserInfo(models.Model):
        uid = models.AutoField(primary_key=True)
        username = models.CharField(max_length=32, unique=True)
        password = models.CharField(max_length=32)
        # "直接定位到media目录下"
        #
        head = models.FileField(upload_to='account/user/%Y%m%d')
        class Meta:
        	db_table = 'T_USER_INFO'
    
  2. 定义FileFiled或者ImageFiled的Form

    class UploadFileForm(forms.Form):
        title = forms.CharField(max_length=50)
        file = forms.FileField()
    
  3. views

    def make_file_name(upload_file_name):
        """
        自定义文件名
        """
           import time, random
            # 文件扩展名
            upload_file_name.rfind([pload_file_name.rfind('.')]:)
            # 定义文件名,年月日时分秒随机数
            fn = time.strftime('%Y%m%d%H%M%S')
            fn = 'IMG_' + fn + '%s' % random.randint(0, 100)
    	 return fn
    
    def save_uploaded_file(uploadFile):
        """
        保存文件
        """
        with open(get_file_name(uploadFile.name), 'wb') as file:
            for chunk in uploadFile.chunks():
                file.write(chunk)
    
    def upload_file(request):
        if request.method == 'POST':
            form = UploadFileForm(request.POST, request.FILES)
           	# 判断是否第一次请求 
            if form.is_valid():
                save_uploaded_file(request.FILES['file'])
                return render(request,'success.html')
        else:
            form = UploadFileForm()
        return render('upload.html', {'form': form})
    
  4. 前端upload.html

    <form action="/upload/" method="post">
        {% csrf_token %}
        {{ form }}
        <input type="submit" value="上传" />
    </form>
    

六、ajax上传

  1. models

    class UserInfo(models.Model):
        uid = models.AutoField(primary_key=True)
        username = models.CharField(max_length=32, unique=True)
        password = models.CharField(max_length=32)
        # "直接定位到media目录下"
        head = models.FileField(upload_to='account/user/%Y%m%d',storage=CustomFileStorage())
        class Meta:
        	db_table = 'T_USER_INFO'
    
  2. views

    def upload(request):
        if request.method == 'POST':
            username = request.POST.get('username')
            password = request.POST.get('password')
            user = UserInfo()
            user.head = request.FILES.get('head')
            user.username = username
            user.password = password
            user.save()
        return render(request, 'index.html')
    
  3. html

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
        <script src="https://cdn.bootcss.com/jquery/3.2.1/jquery.min.js"></script>
        <script language="JavaScript">
            let register_url = 'http://127.0.0.1:8000/day06/register/';
            $(function () {
                $("#register_btn").click(function () {
                    let formdata = new FormData();
                    let fileobj = $('#head')[0].files[0];
                    let username = $('#username').val();
                    let password = $('#password').val();
                    formdata.append('username', username);
                    formdata.append('password', password);
                    formdata.append('head', fileobj);
                    $.ajax(register_url, {
                        type: 'POST',
                        data: formdata,
                        contentType: false,
                        /*告诉jquery不要处理数据*/
                        processData:
                            false,
                        cache:
                            false
                    }) ;
                    return false
                });
            })
        </script>
    </head>
    <body>
    <form id="register"
          action="/day06/register/"
          method="post"
          enctype="multipart/form-data">
        <input type="text" id="username">
        <input type="password" id="password">
        <input type="file" id="head">
        <input type="button" id="register_btn" value="注册">
        <input type="reset" value="重置">
    </form>
    </body>
    </html>
    
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值