django 加载静态图片失败

Posted

技术标签:

【中文标题】django 加载静态图片失败【英文标题】:django failed to load static image 【发布时间】:2019-09-26 03:47:37 【问题描述】:

我的 django 应用程序托管在 pythonanywhere 上。我正在使用 weasyprint 生成一个 pdf,并且在我的 pdf 中显示了一个图像。错误日志中的错误是“无法在 /static/images/logo.png 加载图像”。当我尝试打开与 url 相同的路径时,它会在浏览器中显示图像。这意味着它的路径是正确的,但其他地方是错误的。

我的静态目录放置在应用程序之外。并且这个路径被添加到设置文件中。

我的文件夹结构:

     my_app
     static
        |__ css
        |__ images
              |__ logo.png
        |__ js
     templates
        |__ my_app
              |__ pdf.html

settings.py:

STATIC_DIR = os.path.join(BASE_DIR, 'static')
STATIC_URL = '/static/'
STATICFILES_DIRS =[
    STATIC_DIR,
]

pdf.html:

% load static %
<td><img class="my_logo" src="% static 'images/logo.png' %" ></td>

【问题讨论】:

试试“STATIC_URL = './static/'” 将 STATIC_DIR 重命名为 STATIC_ROOT。并将其从 STATICFILES_DIRS 中删除:STATICFILES_DIRS 是 source 文件夹列表,将在 collectstatic 期间扫描以填充 destination 文件夹 - STATIC_ROOT。 @IvanStarostin 所以实际上 STATICFILES_DIRS 是正确的,因为它 源静态文件所在的位置。缺少的是项目外部的 STATIC_ROOT 目录并运行 manage.py collectstatic 以将静态文件从项目存储库内的静态目录复制到提供它们的位置。 directory outside of the project 好像OP没有这样的目录。 那么 OP 应该添加这样一个目录。你永远不应该在你的项目(源代码)目录中提供静态文件。您的整个项目目录应该只能由您的应用服务器 (WSGI) 访问,而不能由您的 Web 服务器访问。 【参考方案1】:

假设您显示的文件夹结构是您在开发机器上使用的并反映了您的实际代码存储库。

你的设置是正确的:

STATICFILES_DIRS 列出了您放置静态文件的目录(在应用程序之外) STATIC_URL 是用来给静态位置加前缀的url,告诉服务器“任何以此开头的url,你都需要去获取一个静态文件”。

缺少的是:

STATIC_ROOT: collectstatic 应该把你的静态文件复制到哪里?这通常是项目存储库之外的位置,有时甚至在完全不同的机器上,您的 Web 服务器将从那里提供静态文件。在简单的部署中,它可以是与您的项目处于同一级别的 /static 目录:
/home/myusername/my_project_www/
     |_ my_project/   <-- BASE_DIR (this is a git clone of your code)
          |_ my_project
                |_ settings.py
                |_ urls.py
          |_ app/
              |_ views.py
              |_ static/  <-- automatically used as source by Django
          |_ manage.py
          |_ static/  <-- added to STATICFILES_DIRS
          |_ ...
     |_ static/  <-- STATIC_ROOT all files will be copied and served from here
     |_ media/  <-- MEDIA_ROOT if users can upload files

在上面的示例中,您将设置STATIC_ROOT = os.path.abspath(os.path.join(os.path.dirname(BASE_DIR), 'static'))(BASE_DIR 上方的一个目录)。

然后您需要运行manage.py collectstatic,以便将所有静态文件复制到该目录中。

最后在 pythonanywhere 控制台的 Static Files 部分中,您必须将 /static/ url 映射到 STATIC_ROOT 的位置,即/home/username/my_project_www/static/ 代表路径。 (或者,如果您正在运行自己的服务器,则需要在您的 nginx 或 apache 配置中进行配置)。

我已经为此写了blog post。

【讨论】:

解释得很好。谢谢你。 :) 您建议的更改以及所有其他静态文件/图像是否在网站上正确呈现...只是不是我包含在 pdf 中的那个! @VasundharaAgrawal 没有意识到图像会嵌入到 pdf 文件中,即不会作为链接下载。对整个路径进行硬编码可能不是一个好主意,因为如果您在另一个系统上部署它可能会中断。但是,如果您确保将 STATIC_ROOT 作为上下文变量传递给模板渲染,则类似 src="file:// STATIC_ROOT images/logo.png" 的东西会起作用。 好的。谢谢@dirkgroten :) 请注意,如果有一天您决定将静态文件 (STATIC_ROOT) 托管在不同的系统上,例如,file:// 将是一个问题。来自亚马逊的 S3。因为file:// 告诉weazyprint 查看本地文件系统。但是您必须研究 weazyprint 的工作原理才能弄清楚如何编写 src,因为它必须能够使用不同的存储类(而不是 DefaultFileStorage)。 是的,我就是这么想的。【参考方案2】:

您是要制作一个 pdf 供用户下载,还是要显示一个 html 文件?

如果您使用 weasyprint 生成 pdf,则 weasyprint 不会尝试访问 http://yourwebsite/static/images/logo.png 以获取要放入 pdf 的徽标。相反,它会尝试访问您服务器上/static/images/logo.png 上的文件。

如果您只想在 pdf 中添加徽标,则应改为让 weasyprint 说输入来自/home/username/path/to/your/logo/file.png 的徽标。

【讨论】:

谢谢。但是错误日志中的错误是“无法在 http://mywebsite/static/images/logo.png 加载图像”尝试使用您建议的路径仍然显示错误“无法在 http://mywebsite 加载图像” /home/username/static/images/logo.png" 我可以使用绝对文件路径来做到这一点:src="file:///home/username/static/images/logo.png" 但是这样硬编码可以吗?我试过的其他方法似乎都不起作用。 weasy print 可以通过访问文件系统而不是网站来获取徽标来创建pdf。或者在 weasy print 创建 pdf 之后,pdf 本身可以尝试从网站加载徽标,而不是从文件系统加载。我不清楚你想做什么

以上是关于django 加载静态图片失败的主要内容,如果未能解决你的问题,请参考以下文章

Django加载静态文件失败

django开发环境setting.py里面设置debug=false时却成功加载静态文件?

24.FastAPI静态文件

django加载静态文件

Django加载静态文件

有个html静态文件,怎么批量给所有的a标签添加nofollow属性。