Django详情页图片路径拼接slug导致静态资源加载失败排查
问题描述
基于Django搭建的博客项目存在图片加载异常:
- 文章详情页渲染时,会自动在图片路径前拼接当前文章slug,导致图片无法加载
- 完全相同的
post.image字段引用代码,在首页index.html中可正常加载图片 - 问题截图:

实际路径表现:
- 预期正确路径:
http://127.0.0.1:8000/static/placeholder_cake.PNG - 实际错误路径:
http://127.0.0.1:8000/carrot-cake/static/placeholder_cake.PNG(多余拼接了文章slug前缀)
之前尝试调整urls.py路由配置未解决问题。
关联项目代码
index.html
<div class="col-md-8 mt-3 left"> {% for post in post_list %} <div class="card mb-4"> <div class="card-body"> <img class="card-img-top" src="{{ post.image }}" alt="Card image cap"> <h2 class="card-title">{{ post.title }}</h2> <p class="card-text text-muted h6">{{ post.author }} | {{ post.created_on}} </p> <p class="card-text">{{post.content|slice:":200" }}</p> <a href="{% url 'post_detail' post.slug %}" class="btn btn-primary">Read More →</a> </div> </div> {% endfor %} </div>
post_detail.html
{% extends 'base.html' %} {% block content %} <!-- {% load static %} --> <div class="container"> <div class="row"> <div class="col-md-8 card mb-4 mt-3 left top"> <div class="card-body"> <h1>{% block title %} {{ objest.title }} {% endblock title %}</h1> <p class=" text-muted">{{ post.author }} | {{ post.created_on }}</p> <!-- /carrot-cake/static/placeholder_cake --> <img class="card-img-top" src="{{ post.image }}" alt="Card image cap"> <p class="card-text "><pre class="recipe">{{ object.content | safe }}</pre></p> </div> </div> {% block sidebar %} {% include 'sidebar.html' %} {% endblock sidebar %} </div> </div> {% endblock content %}
models.py
class Post(models.Model): title = models.CharField(max_length=200, unique=True) slug = models.SlugField(max_length=200, unique=True) author = models.ForeignKey(User, on_delete= models.CASCADE,related_name='blog_posts') updated_on = models.DateTimeField(auto_now= True) content = models.TextField() created_on = models.DateTimeField(auto_now_add=True) status = models.IntegerField(choices=STATUS, default=0) image = models.ImageField(upload_to='static', null=True, blank=True) class Meta: ordering = ['-created_on'] def __str__(self): return self.title
views.py
class PostList(generic.ListView): queryset = Post.objects.filter(status=1).order_by('-created_on') template_name = 'index.html' class PostDetail(generic.DetailView): model = Post template_name = 'post_detail.html'
urls.py
urlpatterns = [ path('', views.PostList.as_view(), name='home'), path('<slug:slug>/', views.PostDetail.as_view(), name='post_detail'), ]
问题原因
问题和视图、路由逻辑无关,核心是两个问题:
- 相对路径解析规则导致前缀拼接
直接输出{{ post.image }}拿到的是不带开头斜杠的相对路径(比如static/placeholder_cake.PNG),浏览器解析相对路径时,会基于当前页面的URL目录拼接:- 首页URL是根路径
/,相对路径会被解析为/static/placeholder_cake.PNG,刚好符合预期,所以首页显示正常 - 详情页URL是
/carrot-cake/这类子路径,相对路径就会被解析为/carrot-cake/static/placeholder_cake.PNG,导致404
- 首页URL是根路径
- 文件存储配置不符合Django规范
把用户上传的ImageField文件存到了static目录,Django中static目录存的是CSS、JS、固定默认图片这类静态资源,用户上传的文件属于媒体文件,应该单独走media配置,不应该混存。另外模板里直接输出post.image而不是用post.image.url也是不规范的写法。
解决步骤
快速修复路径拼接问题
所有模板中引用图片的位置,给路径前加根路径斜杠,强制从站点根目录解析,比如把src="{{ post.image }}"改成src="/{{ post.image }}",改完立刻就能解决slug拼接的问题。规范媒体文件配置(推荐长期方案)
- 修改models.py的ImageField上传路径,不要存到static目录:
image = models.ImageField(upload_to='post_images/', null=True, blank=True) - 在项目settings.py中添加媒体文件配置:
MEDIA_URL = '/media/' MEDIA_ROOT = BASE_DIR / 'media' - 修改根urls.py,添加开发环境下的媒体文件路由支持:
from django.conf import settings from django.conf.urls.static import static urlpatterns = [ path('', views.PostList.as_view(), name='home'), path('<slug:slug>/', views.PostDetail.as_view(), name='post_detail'), ] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT) - 模板中统一用Django封装的url属性引用图片,把
src="{{ post.image }}"改成src="{{ post.image.url }}",后续不管页面路由怎么变,都不会出现路径拼接错误。
- 修改models.py的ImageField上传路径,不要存到static目录:
修复模板笔误
post_detail.html中标题部分的{{ objest.title }}存在拼写错误,改成{{ object.title }}即可正常渲染文章标题。
内容的提问来源于stack exchange,提问作者Snerd
相关产品推荐
相关产品推荐

