Django后端自动上传文件到FileField无需前端手动选择实现方法
实现方案
核心逻辑是访问接口时由后端直接读取服务器本地预存的data1.py文件,通过Django内置的File类封装后赋值给Result模型的File字段完成入库,全程不需要前端选择、上传文件流。
前置配置
先修正原有代码的问题,同时配置好Django文件存储的必要参数:
- 首先在项目
settings.py中补充媒体文件和本地预存文件目录配置,确保FileField正常工作,同时规避路径遍历风险:
import os from pathlib import Path BASE_DIR = Path(__file__).resolve().parent.parent # 原有配置保留,新增以下内容 MEDIA_URL = '/media/' MEDIA_ROOT = os.path.join(BASE_DIR, 'media') # 本地预存文件的白名单根目录,手动创建该文件夹后将data1.py放入其中 LOCAL_PRESET_FILE_ROOT = os.path.join(BASE_DIR, 'local_preset_files')
- 原代码直接将模型类
Result传给serializer_class是错误用法,需要先在result应用下新建serializers.py编写对应序列化器:
from rest_framework import serializers from .models import Result class ResultSerializer(serializers.ModelSerializer): class Meta: model = Result fields = '__all__'
接口代码改造
修改views.py中的视图类代码,补充路径校验、本地文件读取、模型保存逻辑:
原接口使用GET方法做数据写入不符合HTTP语义,这里调整为POST方法,若坚持使用GET也可正常运行,但不推荐。
import os from django.core.files import File from rest_framework.response import Response from rest_framework.decorators import action from rest_framework import viewsets,status from rest_framework.authentication import TokenAuthentication from rest_framework.permissions import IsAuthenticated from django.conf import settings from .models import Result from .serializers import ResultSerializer class ResultViewSet(viewsets.ModelViewSet): queryset = Result.objects.all() serializer_class = ResultSerializer authentication_classes = (TokenAuthentication,) permission_classes = (IsAuthenticated,) # 该接口不需要传入pk,detail设为False @action(detail=False, methods=['POST']) def resultfill(self, request): # 固定使用data1.py的话可以直接写死文件名,不需要前端传参 file_name = request.data.get('file_name', 'data1.py') target_file_path = os.path.join(settings.LOCAL_PRESET_FILE_ROOT, file_name) # 安全校验:强制校验文件路径在白名单目录内,防止路径遍历攻击 real_file_path = os.path.realpath(target_file_path) if not real_file_path.startswith(os.path.realpath(settings.LOCAL_PRESET_FILE_ROOT)): return Response({'error': '非法文件路径'}, status=status.HTTP_400_BAD_REQUEST) # 校验文件存在性 if not os.path.isfile(real_file_path): return Response({'error': '指定文件不存在'}, status=status.HTTP_404_NOT_FOUND) # 读取本地文件封装为Django文件对象,创建数据库记录 with open(real_file_path, 'rb') as f: django_file = File(f) result_obj = Result.objects.create( Name='预设数据文件', # Name字段可根据业务需求自行赋值 File=django_file ) serializer = self.get_serializer(result_obj) return Response(serializer.data, status=status.HTTP_201_CREATED)
注意事项
- 如果固定使用
data1.py,可以去掉file_name参数获取逻辑,直接写死文件路径,访问接口即可自动完成文件入库,不需要传任何文件相关参数。 - 路径安全校验必须保留,禁止直接读取前端传入的任意路径,否则会产生任意文件读取、服务器敏感信息泄露的高危漏洞。
- 保存时Django会自动将原文件拷贝到
MEDIA_ROOT配置的目录下,不会修改或移动原路径下的data1.py。 - 开发环境下需要在项目根
urls.py中补充媒体文件路由,否则保存后的文件无法通过URL访问:
from django.conf import settings from django.conf.urls.static import static urlpatterns = [ # 原有路由配置保持不变 ] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
内容的提问来源于stack exchange,提问作者Pratish Dewangan
相关产品推荐
相关产品推荐

