You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Django Rest Framework构建的GET API图片URL访问404错误,本地与Heroku环境均无法显示图片

解决DRF API图片URL无法访问及React前端无法展示的问题

我看了你遇到的问题——用Django Rest Framework做的GET API能返回图片URL,但不管是直接点击URL还是React前端都没法正常显示图片,本地和Heroku线上都有这情况。咱们一步步来排查解决:

1. 先搞定MEDIA路径的配置冲突

你现在的模型里image字段的upload_to='media/pictures',而settings里MEDIA_ROOT = os.path.join(BASE_DIR,'media/pictures'),这会导致图片实际存储路径变成BASE_DIR/media/pictures/media/pictures/xxx.jpg,和你预期的完全不符!

模型里的upload_to是相对于MEDIA_ROOT的子路径,所以得把这两个配置统一:

  • 修改模型代码:
    class Menus(models.Model):
        # 其他字段不变
        image = models.ImageField(upload_to='pictures', null=True)  # 去掉前面的media/
    
  • 修改settings.py里的MEDIA_ROOT:
    MEDIA_ROOT = os.path.join(BASE_DIR, 'media')  # 只到media目录,子目录由upload_to控制
    

这样图片会被存在BASE_DIR/media/pictures/xxx.jpg,对应的访问URL就是/media/pictures/xxx.jpg,路径就对了。

2. 修复生产环境的MEDIA路由

你现在的项目URL配置只在DEBUG=True时才加media路由,但Heroku线上环境默认DEBUG=False,所以media文件根本没被服务起来,自然访问不了。

修改项目的urls.py,确保生产环境也能处理media请求:

from django.conf import settings
from django.conf.urls.static import static
from django.views.static import serve

urlpatterns = [
    # 你的现有路由,比如admin、api这些
    path('admin/', admin.site.urls),
    path('api/menus/', include('your_app_name.urls')),
]

# 处理media文件的路由,兼容本地和生产环境
if settings.DEBUG:
    urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
else:
    # 生产环境用serve视图处理media请求
    urlpatterns += [
        path(settings.MEDIA_URL.lstrip('/') + '<path:path>', serve, {'document_root': settings.MEDIA_ROOT}),
    ]

3. 解决Heroku的临时文件系统问题

Heroku的文件系统是临时的,每次部署、重启后,你上传的本地media文件都会丢失,而且上传的图片也不会被Git跟踪(应该在.gitignore里排除了media目录)。所以生产环境必须用云存储来存图片,比如AWS S3或者Cloudinary。

举个Cloudinary的快速配置例子:

  1. 安装依赖:
    pip install cloudinary django-cloudinary-storage
    
  2. 在settings.py里添加配置:
    INSTALLED_APPS += ['cloudinary_storage', 'cloudinary']
    
    # 替换成你自己的Cloudinary账号信息
    CLOUDINARY_STORAGE = {
        'CLOUD_NAME': '你的Cloudinary云名称',
        'API_KEY': '你的API密钥',
        'API_SECRET': '你的API密钥密码'
    }
    
    DEFAULT_FILE_STORAGE = 'cloudinary_storage.storage.MediaCloudinaryStorage'
    

这样上传的图片会自动存在Cloudinary,API返回的URL是Cloudinary的公共地址,不管Heroku怎么重启都不会丢,而且访问速度更快。

4. 确保序列化器生成正确的绝对URL

你写的image_url字段依赖request上下文来生成绝对URL,要确保视图里把request传给序列化器:

from rest_framework import generics
from .models import Menus
from .serializers import MenusSerializer

class MenusListView(generics.ListAPIView):
    queryset = Menus.objects.all()
    serializer_class = MenusSerializer

    def get_serializer_context(self):
        # 把request传入序列化器上下文
        context = super().get_serializer_context()
        context['request'] = self.request
        return context

这样request.build_absolute_uri(image_url)才能生成完整的http/https绝对URL,React前端也能直接用这个URL加载图片。

按上面的步骤改完后,不管本地还是Heroku线上,图片URL应该都能正常访问,React前端也能顺利展示图片了。

内容的提问来源于stack exchange,提问作者Reactoo

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.30 04:44:08