DJango接收上传的文件

526 阅读2分钟

前情提要

在之前我写了一篇文章 Django图片的上传与访问,里面实现了图片的上传与保存,并且在服务器进行访问。但是也因此出现了一个问题:

  • 问题:在模型中的头像字段使用了参数upload_to,这会使图片(或其他文件)自动保存到settings.py定义的MEDIA_ROOT + /upload_to指定的路径下,这非常不方便,我无法将图片(或其他文件)保存到我想要的其他路径中

解决方法

避免使用ImageField或者FileField这样的字段,或者不使用这两个字段中的upload_to参数。那么本次就不使用这个字段。代替使用的是DRF中的解析器用来接收文件

关于DRF中的解析器

解析器如何确定?一组视图的有效解析器总是被定义为一个类的列表。当访问request.data时,REST框架将检查传入请求中的Content-Type头,并确定用于解析请求内容的解析器。本次将会使用MultiPartParser

更多详细内容建议查看:
Django REST framework中文文档-解析器

Django Rest Framework组件:解析器JSONParser、FormParser、MultiPartParser、FileUploadParser

JSONParser

当接收的HTTP请求的请求头为Content-Type:application/json时,使用JSONParser(当视图不添加JsonParser时会自动使用,这也就是说前面的实验一般不添加解析器,默认request.data解析json)

from rest_framework.parsers import JSONParser

class Test(APIView):
    # 在视图类中指定解析器为JSONParser
    parser_classes = [JSONParser, ]
    def post(self,request):
        """ 实现逻辑... """
        ...

FormParser

当接收的HTTP请求头为Content-Type:application/x-www-form-urlencoded时,使用FormParser

from rest_framework.parsers import FormParser

class Test(APIView):
    # 在视图类中指定解析器为FormParser
    parser_classes = [FormParser, ]
    def post(self,request):
        """ 实现逻辑... """
        ...

MultiPartParser

当接收的HTTP请求头为Content-Type:multipart/form-data时,使用MultiPartParser

from rest_framework.parsers import MultiPartParser

class Test(APIView):
    # 在视图类中指定解析器为MultiPartParser
    parser_classes = [MultiPartParser, ]
    def post(self,request):
        """ 实现逻辑... """
        ...

使用MultiPartParser接收文件

在项目下创建子引用user
现在有模型user/models.py,如下:

class User(models.Model):
    user_name = models.CharField(max_length=20,unique=True) # 用户名
    user_password = models.CharField(max_length=15) # 用户密码
    """ 其他字段... """
    
    # 该字段保存服务器的静态资源的访问地址
    user_header_pro = models.CharField(max_length=100) # 用户头像

设置子路由user/urls.py,如下:

re_path('^userheaderpro/(?P<pk>\d+)$',views.UserHeaderPro.as_view())

视图user/views.py,如下:

from rest_framework.parsers import MultiPartParser

class UserHeaderPro(APIView):
    # 使用 MultiPartParser 解析器,接收前端传过来的content-type为fromdata的数据
    parser_classes = [MultiPartParser,]
    
    def put(self,request,pk):
        user = User.objects.get(id = pk)

        """ 1.由于有MultiPartParser解析器,可以通过request.data.get()获取文件 """
        file =request.data.get('user_header_pro')
        """ 2.获取 media文件夹的路径\user个人文件夹(在注册的时候分配给用户据一个用户数据文件夹)\前端传过来的文件名(str(user_header_pro)可获取文件名) """
        temp_url = str(settings.MEDIA_ROOT) + '\\' + str(user.id) + '\\' + str(user_header_pro)
        with open(temp_url,'wb') as f:
            for chunk in file.chunks():
                f.write(chunk)
        return Response({"msg":"上传成功"})

这样上传的文件就保存到了指定的文件夹下面