在Heroku上部署Django项目后调用API获取图片出现404错误的问题排查
Hey there, let's break down why your images aren't showing up and fix this step by step. Looking at the image URL you shared (https://bookcake.herokuapp.com/api/cake/media/None/rlvdmseoghk.jpg), the big red flag is the None in the path—this is the primary culprit right now. Here are the most likely causes and fixes:
1. Your ImageField's upload_to Configuration Is Broken
The None in the image path suggests that the upload_to parameter for your model's ImageField is returning an invalid value (like None instead of a valid directory path).
- Check your model definition: Make sure
upload_tois set to a valid string or a function that returns a proper path string. For example:# Good: Static directory image = models.ImageField(upload_to='cake_images/') # Good: Dynamic path function (if you're using one) def cake_image_path(instance, filename): # Returns a path like "cake_1/rlvdmseoghk.jpg" return f"cake_{instance.id}/{filename}" image = models.ImageField(upload_to=cake_image_path) - If you're using a custom
upload_tofunction, debug it to ensure it never returnsNone—that's exactly what's inserting that invalid segment into your image URL.
2. Heroku Doesn't Serve Media Files By Default
Even if you fix the None path issue, Heroku's ephemeral filesystem and default setup won't serve media files out of the box. Here are two common solutions:
Option A: Use Cloud Storage (Recommended)
Heroku's temporary filesystem deletes all uploaded files after app restarts, so storing media on a cloud service is the long-term, reliable fix. You'll need:
- Install a storage library like
django-storages - Configure it to connect to your chosen cloud storage (e.g., AWS S3)
- Update your settings to point
DEFAULT_FILE_STORAGEto the cloud storage backend - This will make your image URLs point directly to the cloud service instead of your Heroku app, eliminating path and serving issues entirely.
Option B: Use Whitenoise to Serve Media Files (For Testing Only)
If you're just testing and don't need persistent storage, you can use Whitenoise to serve media files:
- Install Whitenoise:
pip install whitenoise - Update your
settings.py:INSTALLED_APPS = [ 'whitenoise.runserver_nostatic', # Add this first 'django.contrib.staticfiles', # ... rest of your apps ] MIDDLEWARE = [ # ... other middleware (place after SecurityMiddleware) 'whitenoise.middleware.WhiteNoiseMiddleware', ] # Allow Whitenoise to serve media files WHITENOISE_ROOT = os.path.join(BASE_DIR, 'media') STATICFILES_STORAGE = 'whitenoise.storage.CompressedManifestStaticFilesStorage' - Remove the
static(settings.MEDIA_URL, ...)line from yoururls.pyin production—Whitenoise handles this automatically.
3. Your URL Routing for Media Files Is Misconfigured
Looking at the URL path /api/cake/media/..., it seems your media routes might be nested under your API's api/cake namespace, which is unnecessary and could cause path conflicts.
- Ensure your media file routes are at the top level of your
urls.py(not inside aninclude('api.cake.urls')block). For development, the standard setup is:from django.conf import settings from django.conf.urls.static import static urlpatterns = [ # ... your API and other routes ] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT) - In production, this line should be removed (since you'll use Whitenoise or cloud storage instead).
Start with fixing the upload_to issue first—once the None is gone from your image URL, you can tackle the media serving problem on Heroku.
内容的提问来源于stack exchange,提问作者Ryan

