如何修复Django Summernote图片集成中src URL为相对路径导致无法显示的问题
Hey there! I've dealt with this exact problem before when working with Django Summernote—admin works fine but frontend images break because of relative paths. Let's walk through the most effective fixes for your Django 3.1 project:
1. Update MEDIA_URL to Use Absolute Paths (Environment-Specific)
Summernote uses your MEDIA_URL setting to generate image paths when uploading. If it's set to a relative path (/media/), the frontend will render relative URLs. To fix this, make MEDIA_URL an absolute path tailored to your environment:
# settings.py import os from django.conf import settings BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) MEDIA_ROOT = os.path.join(BASE_DIR, 'media/') # Handle development and production environments if settings.DEBUG: # For local Docker setup (matches your localhost:8000) MEDIA_URL = 'http://localhost:8000/media/' else: # Replace with your remote server's domain when deploying MEDIA_URL = 'https://your-production-domain.com/media/'
This ensures Summernote saves full absolute paths for images right from upload.
2. Configure Summernote to Force Absolute Attachment URLs
If you prefer keeping MEDIA_URL relative (for flexibility), you can explicitly tell Django Summernote to use absolute URLs for attachments. Add this to your settings.py:
# settings.py SUMMERNOTE_CONFIG = { # Keep your existing Summernote config, add these lines: 'attachment_absolute_uri': True, 'attachment_upload_to': 'django-summernote/', # Match your existing upload path }
This setting overrides the default relative path behavior for Summernote attachments, ensuring every uploaded image gets a full URL.
3. Fix Frontend Rendering with a Custom Template Filter
If changing backend settings isn't an option (or you need to retroactively fix existing content), create a template filter to convert relative /media/ paths to absolute URLs:
Step 1: Create a Template Tag File
In your app directory, make a templatetags folder (if it doesn't exist) with a file like summernote_filters.py:
# yourapp/templatetags/summernote_filters.py from django import template from django.conf import settings from django.contrib.sites.shortcuts import get_current_site register = template.Library() @register.filter def absolute_media(content): # Get the full media URL (including domain) if not settings.MEDIA_URL.startswith(('http://', 'https://')): request = template.context_processors.request(None)['request'] site_domain = get_current_site(request).domain # Use http or https based on your environment media_base = f"http://{site_domain}{settings.MEDIA_URL}" else: media_base = settings.MEDIA_URL # Replace relative paths with absolute ones return content.replace('/media/', media_base)
Step 2: Use the Filter in Your Template
Load the filter and apply it when rendering Summernote content:
<!-- your_template.html --> {% load summernote_filters %} <!-- Render the content with absolute media URLs --> {{ your_summernote_content|absolute_media|safe }}
4. Verify Media Serving in URLs.py
Double-check that your urls.py correctly serves media files (critical for local development):
# urls.py from django.conf import settings from django.conf.urls.static import static from django.contrib import admin from django.urls import path, include urlpatterns = [ path('admin/', admin.site.urls), path("summernote/", include("django_summernote.urls")), # Your other routes... ] # Serve media files in DEBUG mode if settings.DEBUG: urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
You mentioned absolute paths work, so this is likely already set up—but it's worth confirming to rule out other issues.
Pick the solution that fits your workflow best! The first two options fix the problem at the source, while the third is great for existing content.
内容的提问来源于stack exchange,提问作者Dany

