如何使用Django REST Framework提供Media目录服务?如何编写对应API视图?
Hey there! Let's break down your two Django REST Framework requirements and get you sorted with the right code for views.py.
Before writing any views, you need to make sure your Django project is properly configured to serve media files. Here's what to do first:
Step 1: Configure Media Paths in settings.py
Add these lines to your project's settings.py to define where media files are stored and how they're accessed via URLs:
import os from pathlib import Path BASE_DIR = Path(__file__).resolve().parent.parent MEDIA_ROOT = os.path.join(BASE_DIR, 'media') # Local path to store media files MEDIA_URL = '/media/' # URL prefix for accessing media files
Step 2: Add Media Routes to Project urls.py
In your project's root urls.py, add the route to serve media files. For development environments, Django's built-in static.serve works fine:
from django.conf import settings from django.conf.urls.static import static from django.urls import path, include urlpatterns = [ path('admin/', admin.site.urls), path('api/', include('your_app.urls')), # Your app's API routes # ... other routes ] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
Note: For production, avoid using Django to serve media files directly—use a web server like Nginx or Apache instead for better performance.
Now let's write the view in your app's views.py that returns all files in the media directory when a GET request is made. We'll use DRF's APIView for this:
Full views.py Code
import os from django.conf import settings from rest_framework.views import APIView from rest_framework.response import Response from rest_framework import status from rest_framework.permissions import AllowAny # Or use IsAuthenticated if you need auth class MediaFilesListView(APIView): # Optional: Restrict access to authenticated users only # permission_classes = [IsAuthenticated] permission_classes = [AllowAny] def get(self, request): media_root = settings.MEDIA_ROOT media_files = [] # Walk through the media directory to collect all files for root, _, files in os.walk(media_root): for filename in files: # Skip hidden files (like .DS_Store on macOS) if filename.startswith('.'): continue # Build full local path to the file local_file_path = os.path.join(root, filename) # Get relative path from media root to build the URL relative_path = os.path.relpath(local_file_path, media_root) # Convert OS-specific path separators to URL slashes url_path = relative_path.replace(os.sep, '/') # Build absolute URL for the file file_url = request.build_absolute_uri(f"{settings.MEDIA_URL}{url_path}") # Add file details to the response list media_files.append({ 'filename': filename, 'file_url': file_url, 'file_size_bytes': os.path.getsize(local_file_path), 'relative_path': relative_path }) return Response(media_files, status=status.HTTP_200_OK)
Add the Route to Your App's urls.py
Don't forget to map this view to a URL in your app's urls.py:
from django.urls import path from .views import MediaFilesListView urlpatterns = [ # ... other app routes path('media-files/', MediaFilesListView.as_view(), name='list-media-files'), ]
Extra Tips
- Pagination: If you have a lot of media files, add pagination using DRF's
PageNumberPaginationto avoid returning too much data at once. - File Filtering: You can modify the code to filter files by extension (e.g., only return
.pngor.pdffiles) by checkingfilename.endswith('.png'). - Error Handling: Add try-except blocks around
os.walkoros.path.getsizeto handle cases where the media directory doesn't exist or files are inaccessible.
内容的提问来源于stack exchange,提问作者D_M

