如何用Django Rest Framework实现媒体目录读写与文件链接返回?
使用Django Rest Framework实现Media目录的读写与文件列表接口
刚好做过类似的需求,我来一步步帮你实现想要的功能——允许用户读写media目录,同时GET请求返回指定格式的文件链接列表。
一、先配置Media目录的基础设置
首先得让Django正确识别你的media目录,在项目的settings.py里添加以下配置:
import os BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) # 配置Media目录路径(对应你的myproject/media结构) MEDIA_ROOT = os.path.join(BASE_DIR, 'myproject', 'media') # 配置Media访问的URL前缀 MEDIA_URL = '/media/'
然后在项目根目录的urls.py里添加media文件的访问路由,这样Django才能处理media文件的下载请求:
from django.conf import settings from django.conf.urls.static import static from django.urls import path, include urlpatterns = [ # 其他路由,比如你的app路由 path('api/', include('yourapp.urls')), ] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
二、实现文件上传+文件列表的视图
接下来用DRF写一个视图,同时处理文件上传的POST请求和返回文件列表的GET请求。在你的app里创建/修改views.py:
from django.conf import settings from django.core.files.storage import default_storage from django.http import JsonResponse from rest_framework.views import APIView from rest_framework.parsers import MultiPartParser, FormParser from rest_framework.response import Response from rest_framework import status import os class MediaFileView(APIView): # 处理文件上传需要的解析器 parser_classes = (MultiPartParser, FormParser) def get(self, request): # 遍历media目录下的所有文件,生成指定格式的JSON media_files = {} file_index = 1 for filename in os.listdir(settings.MEDIA_ROOT): file_path = os.path.join(settings.MEDIA_ROOT, filename) # 只处理文件,跳过子目录 if os.path.isfile(file_path): # 生成文件的绝对访问链接 file_url = request.build_absolute_uri(f"{settings.MEDIA_URL}{filename}") media_files[f'file{file_index}'] = file_url file_index += 1 return JsonResponse(media_files) def post(self, request): # 获取上传的文件 uploaded_file = request.FILES.get('file') if not uploaded_file: return Response({"error": "No file uploaded"}, status=status.HTTP_400_BAD_REQUEST) # 保存文件到media目录 file_path = os.path.join(settings.MEDIA_ROOT, uploaded_file.name) # 可选:避免文件名重复,这里做了简单的冲突检查,你可以改成自动重命名逻辑 if default_storage.exists(file_path): return Response({"error": "File already exists"}, status=status.HTTP_409_CONFLICT) default_storage.save(file_path, uploaded_file) # 返回上传成功的信息和文件链接 file_url = request.build_absolute_uri(f"{settings.MEDIA_URL}{uploaded_file.name}") return Response({"message": "File uploaded successfully", "file_url": file_url}, status=status.HTTP_201_CREATED)
这里的关键点:
- GET方法会自动遍历media目录,生成
{"file1": "链接", "file2": "链接"}格式的响应,编号随文件数量自动递增。 - POST方法支持单文件上传,同时做了基础的文件名冲突检查,你可以根据需求扩展(比如给重复文件名加时间戳后缀)。
三、配置视图的路由
在你的app的urls.py里添加路由,把刚才的视图映射到URL:
from django.urls import path from .views import MediaFileView urlpatterns = [ path('media-files/', MediaFileView.as_view(), name='media-files'), ]
四、测试功能
现在可以验证功能了:
- 获取文件列表:发送GET请求到
http://你的域名/api/media-files/,如果media目录有2个文件,会返回:{"file1": "http://你的域名/media/example1.txt", "file2": "http://你的域名/media/example2.txt"} - 上传文件:用POST请求(multipart/form-data格式)发送文件到同一个URL,参数名填
file,成功后会返回文件的访问链接。 - 下载文件:直接访问返回的文件链接,就能下载media目录里的文件了。
额外提醒
- 如果需要权限控制(比如只允许登录用户访问),可以给视图添加DRF的权限类,比如
permission_classes = [IsAuthenticated]。 - 生产环境下,建议用Nginx或其他静态文件服务器处理media文件的访问,不要依赖Django自带的
static路由(性能较差)。 - 如果media目录文件很多,可以给GET请求添加分页逻辑,避免返回过大的响应。
内容的提问来源于stack exchange,提问作者D_M
相关产品推荐
相关产品推荐

