技术博客
DRF框架下的图片(文件)上传
1、最终效果
2、图片上传
alpha阶段实现了拥有题目和正文字段的意见反馈功能,为了更好的让用户反馈bug,beta阶段新增了图片上传功能。
最终效果的实现难点主要在图片上传上,一开始觉得只是在原有的comments app中添加ImageField,再修改post方法即可,应该比较简单。但由于相关资料较少,DRF官方的API也并没有说明,只得作罢。
参考相关教程后(当然不止这一个…是最后发现这样可以有效解决问题),利用html自带的form以及其action字段与后台api/comments进行交互,
注意到enctype的选取一定要为multipart/form-data。
<form target="form" method="post" enctype="multipart/form-data" action='http:127.0.0.1:8000/api/comments/'></form>
处理完前端的交互之后,决定将上传图片传至前端media/usr_img文件夹下,因此修改settings.py,添加设置项如下:
settings.py
MEDIA_ROOT = os.path.join(FONT_DIR, 'media')
MEDIA_URL = '/media/'
X_FRAME_OPTIONS = 'ALLOWALL'
XS_SHARING_ALLOWED_METHODS = ['POST','GET','OPTIONS', 'PUT', 'DELETE']
接着改写后端视图中的post请求处理,由于用户可能不传图片,因此需要利用try块进行处理,未上传图片时则显示默认图片default.jpg。
注意@csrf_exempt,需要支持跨域访问,否则上传文件会失败,上面X_FRAME_OPTIONS = 'ALLOWALL'
和XS_SHARING_ALLOWED_METHODS = ['POST','GET','OPTIONS', 'PUT', 'DELETE']
也是跨域相关的设置。
@csrf_exempt
def post(self, request):
try:
pic = request.FILES['pic']
data = {
"title": request.POST["title"],
"context": request.POST["context"],
"pic": request.POST["title"] + pic.name,
}
save_path = "%s/usr_img/%s" % (settings.MEDIA_ROOT, request.POST["title"] + pic.name,)
print(save_path)
with open(save_path, "wb") as f:
for content in pic.chunks():
f.write(content)
f.close()
except:
data = {
"title": request.POST["title"],
"context": request.POST["context"],
"pic": "default.jpg",
}
serializer = CommentSerializer(data=data)
if serializer.is_valid():
serializer.save()
return Response(serializer.data, status=status.HTTP_201_CREATED)
else:
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
3、不足
该方法并没有表单验证过程。服务器安全性可能会受到影响。