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

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 &rarr;</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'),
]
问题原因

问题和视图、路由逻辑无关,核心是两个问题:

  1. 相对路径解析规则导致前缀拼接
    直接输出{{ post.image }}拿到的是不带开头斜杠的相对路径(比如static/placeholder_cake.PNG),浏览器解析相对路径时,会基于当前页面的URL目录拼接:
    • 首页URL是根路径/,相对路径会被解析为/static/placeholder_cake.PNG,刚好符合预期,所以首页显示正常
    • 详情页URL是/carrot-cake/这类子路径,相对路径就会被解析为/carrot-cake/static/placeholder_cake.PNG,导致404
  2. 文件存储配置不符合Django规范
    把用户上传的ImageField文件存到了static目录,Django中static目录存的是CSS、JS、固定默认图片这类静态资源,用户上传的文件属于媒体文件,应该单独走media配置,不应该混存。另外模板里直接输出post.image而不是用post.image.url也是不规范的写法。
解决步骤
  1. 快速修复路径拼接问题
    所有模板中引用图片的位置,给路径前加根路径斜杠,强制从站点根目录解析,比如把src="{{ post.image }}"改成src="/{{ post.image }}",改完立刻就能解决slug拼接的问题。

  2. 规范媒体文件配置(推荐长期方案)

    • 修改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 }}",后续不管页面路由怎么变,都不会出现路径拼接错误。
  3. 修复模板笔误
    post_detail.html中标题部分的{{ objest.title }}存在拼写错误,改成{{ object.title }}即可正常渲染文章标题。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.28 14:57:18