前情提要
在之前我写了一篇文章 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":"上传成功"})
这样上传的文件就保存到了指定的文件夹下面