如何使用在 Heroku/OpenShift/etc 上具有硬编码相对路径的 django 提供静态文件? [英] How to serve static files with django that has hardcoded relative paths on Heroku/OpenShift/etc?

查看:21
本文介绍了如何使用在 Heroku/OpenShift/etc 上具有硬编码相对路径的 django 提供静态文件?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我拥有由第三方(我无法控制)提供的 HTML/JS/CSS 文件,这些文件用作单页应用程序,与使用 Django 和 django-rest-framework 构建的后端进行通信.

I have HTML/JS/CSS files provided by a third party (whom I have no control over) that serves as a single page app that communicates with a backend built with Django and django-rest-framework.

我想在 Heroku 上托管它,因此这些静态资产由 Django 提供服务.这些文件包含彼此的相对路径.例如,index.html 包含:

I'm wanting to host this on Heroku and thus these static assets are being served by Django. These files contains relative paths to each other. For example, the index.html contains:

<link rel="stylesheet" type="text/css" media="screen" href="styles/css/bootstrap.min.css">

这会导致 404,因为 styles/css/bootstrap.min.css 不是由 django 路由的.

Which leads to a 404 because styles/css/bootstrap.min.css is not routed by django.

我所知道的从我的域根目录 www.domain.com 提供 index.html 的唯一方法是使用如下 url 配置:

The only way I know of to serve the index.html from my domain root www.domain.com is with an url config like:

url(r'^$', TemplateView.as_view(template_name='index.html'), name='home'),

...尽管它不是真正的模板,但它只是普通的 HTML.

...even though it's not really a template, it's just plain HTML.

问题出在其他资产中的所有 url 都与此 index.html 相关的事实,当然 Django 不会那样工作.如果我正在开发这个前端应用程序,我将使用 static 模板标记和获取 javascript url 的各种方法之一.

The problem arises from the fact that all the urls in the other assets are relative to this index.html and of course Django doesn't work like that. If I was developing this front-end application I'd be using the static template tag and one of the various ways to get urls to javascript.

我不介意从 Heroku 切换到另一个 PaaS,如果他们提供了解决此问题的方法,但是手动编辑所有这些文件听起来并不是一件有趣的工作......尤其是考虑到我将收到更新的事实到这些文件继续前进.

I don't mind switching from Heroku to another PaaS if they offer a solution to this problem, but manually editing all these files does not sound like a fun job...especially considering the fact that I'll be receiving updates to these files going forward.

认为在常规旧服务器上解决此问题的方法是配置 Web 服务器以正确解析这些 url,但该选项在 Heroku 上似乎不可用.>

I think the way to solve this on a regular old server would be to configure the web server to resolve these urls correctly, but that option doesn't seem to be available on Heroku.

推荐答案

这里是如何设置 Django 以在/上为您的静态文件和 index.html 提供服务,同时仍然可以将 Django 视图用于管理仪表板、注册等.

Here's how to set up Django to serve your static files and index.html on / while still having the possibility to use Django views for the admin dashboard, registration etc.

from django.conf.urls import include, url
from django.contrib import admin
from django.contrib.staticfiles.views import serve
from django.views.generic import RedirectView

admin.autodiscover()

urlpatterns = [

    # / routes to index.html
    url(r'^$', serve,
        kwargs={'path': 'index.html'}),

    # static files (*.css, *.js, *.jpg etc.) served on /
    # (assuming Django uses /static/ and /media/ for static/media urls)
    url(r'^(?!/?static/)(?!/?media/)(?P<path>.*..*)$',
        RedirectView.as_view(url='/static/%(path)s', permanent=False)),

    # other views still work too
    url(r'^admin/', include(admin.site.urls)),
]

我将 urlpatterns 指定为列表,因为 Django 1.10 需要.自 1.9 以来,重定向默认为非永久性,因此您需要明确设置 permanent=True如果您希望浏览器缓存它,但在调试时我发现最好从 False 开始.

I specify urlpatterns as a list, as Django 1.10 requires. The redirects are not permanent by default since 1.9, so you need to explicitly set permanent=True if you want browsers to cache this, though when debugging I find it better to start with False.

这种方法允许您使用诸如 create-react-appYeoman 前端生成器,将构建的、缩小的前端应用程序打包到一个文件夹中(如 dist/).然后你例如使用脚本将其移动到 Django 的静态文件文件夹(例如 myproject/static/)并从 Heroku 提供.

This approach allows you to use something like create-react-app or Yeoman frontend generators that package a built, minified frontend app into a single folder (like dist/). You then e.g. use a script to move that into Django's static files folder (e.g. myproject/static/) and serve it from Heroku.

Ian 写的关于想要为静态文件使用 S3 之类的东西的文章,但有时您只想从一个存储库、一个 Heroku dyno 开始,并且仍然能够使用 Django + SPA.此外,使用诸如 WhiteNoise 之类的东西可以使从 Python 提供静态文件非常好,并允许您稍后轻松放入CDN放在静态文件前面.

What Ian wrote about wanting to use something like S3 for your static files stands, but sometimes you just want to start simple with one repository, one Heroku dyno and still be able to use Django + a SPA. Also, using something like WhiteNoise makes serving static files from Python pretty OK and allows you to later on easily put a CDN in front of your static files.

注意:对于用户上传的文件,您仍应使用外部服务,如 Amazon S3 或 Backblaze B2(这是 整合).

Note: for user-uploaded files you should still use an outside service like Amazon S3 or Backblaze B2 (which is 4 lines of code to integrate).

WhiteNoise 不适合为用户上传的媒体"文件提供服务.一方面,如上所述,它只在启动时检查静态文件,因此不会看到应用程序启动后添加的文件.但更重要的是,从与主应用程序相同的域提供用户上传的文件存在安全风险(这篇来自 Google 安全性的博文 很好地描述了这个问题).除此之外,使用本地磁盘来存储和提供用户媒体会使您的应用跨多台机器扩展变得更加困难.

Serving Media Files

WhiteNoise is not suitable for serving user-uploaded "media" files. For one thing, as described above, it only checks for static files at startup and so files added after the app starts won’t be seen. More importantly though, serving user-uploaded files from the same domain as your main application is a security risk (this blog post from Google security describes the problem well). And in addition to that, using local disk to store and serve your user media makes it harder to scale your application across multiple machines.

出于所有这些原因,最好将文件存储在单独的专用存储服务上并从那里为用户提供服务.django-storages 库提供了许多选项,例如Amazon S3、Azure 存储和 Rackspace CloudFiles.

For all these reasons, it’s much better to store files on a separate dedicated storage service and serve them to users from there. The django-storages library provides many options e.g. Amazon S3, Azure Storage, and Rackspace CloudFiles.

注意 2:在使用 DEBUG=False 的生产中存在问题,因此请查看 这个白噪声问题寻求解决方案.

Note 2: on production with DEBUG=False there are issues, so check out this WhiteNoise issue for a solution.

注意 3: 将此答案转化为博客文章 这里.

注意 4: 自从写这篇文章以来,我一直在为前端路由调整越来越多的解决方案,所以我最终发布了一个新的 django-spa 包,适用于从 Django 提供单页应用程序的简单服务.

Note 4: since writing this, I've been tweaking the solution more and more for frontend routing, so I ended up releasing a new django-spa package suited for simple serving of single-page apps from Django.

这篇关于如何使用在 Heroku/OpenShift/etc 上具有硬编码相对路径的 django 提供静态文件?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆