Django媒体图片访问404错误排查求助
问题现象
尝试获取媒体图片时出现404错误
URL配置(应用级)
from django.urls import include, path from rest_framework import routers from django.conf.urls.static import static from django.conf import settings from my_awesome_api.views import PersonViewSet, SpeciesViewSet router = routers.DefaultRouter() router.register(r'people', PersonViewSet) router.register(r'species', SpeciesViewSet) urlpatterns = [ path('', include(router.urls)), ] urlpatterns+= static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT) print('avail url patterns') print(urlpatterns)
视图配置
from django.shortcuts import render from rest_framework import viewsets from rest_framework.parsers import MultiPartParser, FormParser from rest_framework import permissions from my_awesome_api.serializers import PersonSerializer, SpeciesSerializer from my_awesome_api.models import Person, Species class PersonViewSet(viewsets.ModelViewSet): queryset = Person.objects.all() serializer_class = PersonSerializer parser_classes = (MultiPartParser, FormParser) #permission_classes = [permissions.IsAuthenticatedOrReadOnly] def perform_create(self, serializer): serializer.save() class SpeciesViewSet(viewsets.ModelViewSet): queryset = Species.objects.all() serializer_class = SpeciesSerializer parser_classes = (MultiPartParser, FormParser) #permission_classes = [permissions.IsAuthenticatedOrReadOnly] def perform_create(self, serializer): serializer.save()
模型配置
from django.db import models # Create your models here. class Species(models.Model): name = models.CharField(max_length=100) classification = models.CharField(max_length=100) language = models.CharField(max_length=100) image_url = models.ImageField(blank=True, null=True) class Person(models.Model): name = models.CharField(max_length=100) birth_year = models.CharField(max_length=10) eye_color = models.CharField(max_length=10) species = models.ForeignKey(Species, on_delete=models.DO_NOTHING) image_url = models.ImageField(blank=True, null=True)
设置配置
MEDIA_ROOT = os.path.join(os.path.dirname(BASE_DIR), 'media') print(MEDIA_ROOT) print('value of media root') # URL used to access the media MEDIA_URL = 'media/'
已做排查
- 已确认MEDIA_ROOT路径正确:
/Users/ss1/Desktop/drf/media - 打印URL配置输出:
[<URLResolver (None:None) ''>, <URLPattern '^media/(?P.*)$'>] - 项目级URL配置:
from django.contrib import admin from django.urls import path, include urlpatterns = [ path("admin/", admin.site.urls), path('star-wars/', include('my_awesome_api.urls')), ]
- 图片已成功上传:

问题原因与解决方法
问题出在媒体URL的配置位置:你把static(settings.MEDIA_URL...)添加到了应用级的urls.py里,但应用是通过star-wars/路径被项目级URL包含的,这导致媒体文件的访问路径被解析为star-wars/media/xxx,但序列化器返回的图片URL是media/xxx,直接访问根路径下的media/时,项目级URL里没有对应的路由,所以返回404。
解决步骤:
- 删除应用级
urls.py中的媒体URL配置代码:
# 移除以下内容 urlpatterns+= static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT) print('avail url patterns') print(urlpatterns)
- 将媒体URL配置添加到项目级的
urls.py中,修改后代码如下:
from django.contrib import admin from django.urls import path, include from django.conf.urls.static import static from django.conf import settings urlpatterns = [ path("admin/", admin.site.urls), path('star-wars/', include('my_awesome_api.urls')), ] # 添加媒体URL路由 urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
额外注意:确保项目DEBUG模式处于开启状态(DEBUG=True),因为static()函数仅在DEBUG模式下生效,生产环境需用Nginx等服务托管媒体文件。
内容的提问来源于stack exchange,提问作者RKs
相关产品推荐
相关产品推荐

