如何部署连接到 Django RESTful API 的静态网站?
How to deploy static website connecting to Django RESTful API?
首先,google 或 SO 搜索对我没有帮助:很多关于 django 静态文件的提示,我认为这些与这里无关。
我继承了一个项目,包括:
- Django 后端以 API 形式仅返回 JSON 响应;
- 标准 Swampdragon 部署将实时更新推送到前端;这里只做了很少的配置;
- 基于 Backbone 和 marionette.js 构建的前端 Web 应用程序,由 Grunt 编译和缩小。
我的问题是:前端需要知道 swampdragon 和 django 服务器的地址;现在这些值是硬编码的,所以有一个 Backbone 模型,其中包含如下行:
url: function() {
return App.BACKEND_URL+'settings/map';
}
为什么要硬编码:后端可以在任何端口上提供服务或拥有自己的子域;前端是静态的,通常会简单地放入 /var/www(对于 Apache)或使用一些非常简单的 nginx 配置。两者将从同一个地方提供服务,但不能保证端口号或子域匹配。
想法 1:通过获取 window.location.host 并附加标准端口,尝试猜测 javascript 中的 BACKEND_URL 是什么。这很骇人听闻而且容易出错。
想法 2:将前端移至 Django 并使其询问 swampdragon 凭据(它们将在主页视图的上下文中发送)。问题在于,前端文件是由 grunt 编译的。所以 Django 会期待这样的东西:
<script src="{% static 'scripts/vendor/modernizr.js' %}"></script>
其实我有
<script src="scripts/vendor/a8bcb0b6.modernizr.js"></script>
其中 'a8bcb0b6' 是 grunt 的 hash/version 编号,将在下一个 minification/build 期间重新生成。我是否需要添加额外的逻辑来摆脱这些东西并将 grunt 的输出目录复制到 django 的静态和模板目录?
或者还有其他方法可以使这项工作,正确的方法,我错过了?
你的架构已经很干净了,不需要让 Django 知道 g运行t 或提供静态文件,也不需要使用 JS hacks 来猜测端口号
反向代理
使用 反向代理 像 nginx 或任何其他您喜欢的 Web 服务器作为静态文件 和 REST 的前端API.
In computer networks, a reverse proxy is a type of proxy server that
retrieves resources on behalf of a client from one or more servers.
These resources are then returned to the client as though they
originated from the proxy server itself. (Wikipedia)
我将概述重要方面,但不会过多介绍细节:
URL 用于 REST API
我们进行配置,以便 nginx 将 API 请求转发给 Django
location /api {
proxy_pass http://127.0.0.1:8000; # assumes Django listens here
proxy_set_header Host $http_host; # preserve host info
}
所以上面假设你的 Django REST 被映射到端口 8000
上的 /api
和 运行s(例如你可以 运行 gunicorn 在那个端口上,或者任何您喜欢的其他服务器)
http://nginx.org/en/docs/http/ngx_http_proxy_module.html
URL 用于我们的前端应用程序
接下来 nginx 将提供来自 g运行t 的静态文件,只需将其指向静态文件夹
location / { alias /app/static/; }
以上假定您的静态资源位于 /app/static/
文件夹中(例如 index.html
、您的 CSS、JS 等)。所以这主要是为了加载您的 BackboneJS 应用程序。
Django 静态文件
下一步不是必需的,但如果您有与 Django 应用程序一起使用的静态文件(使用 ./manage.py collectstatic
生成的静态文件,例如 Django 管理员或 Django 的 UI REST Framework 等),只需根据您的 Django settings.py
STATIC_URL
和 STATIC_ROOT
进行映射
location /static { alias /app/django_static_root/; }
/static
和django_static_root
分别是STATIC_URL
和STATIC_ROOT
总结
例如当你点击 example.com/
时,nginx 只是提供静态文件,然后当 JS 脚本对 /api
进行 REST 调用时,它会被困在 /api
nginx 位置并转发给 Django
最终结果是,example.com/
和 example.com/api
都访问了同一个前端 Web 服务器,该服务器将它们代理到正确的位置
好了,保留代理解决了您的端口和子域问题(以及许多其他问题,例如来自 Django 的缓慢静态文件和 Web 浏览器和防火墙中的同源策略,除了默认的 HTTP 和 HTTPS 端口外不喜欢任何东西)
首先,google 或 SO 搜索对我没有帮助:很多关于 django 静态文件的提示,我认为这些与这里无关。
我继承了一个项目,包括:
- Django 后端以 API 形式仅返回 JSON 响应;
- 标准 Swampdragon 部署将实时更新推送到前端;这里只做了很少的配置;
- 基于 Backbone 和 marionette.js 构建的前端 Web 应用程序,由 Grunt 编译和缩小。
我的问题是:前端需要知道 swampdragon 和 django 服务器的地址;现在这些值是硬编码的,所以有一个 Backbone 模型,其中包含如下行:
url: function() {
return App.BACKEND_URL+'settings/map';
}
为什么要硬编码:后端可以在任何端口上提供服务或拥有自己的子域;前端是静态的,通常会简单地放入 /var/www(对于 Apache)或使用一些非常简单的 nginx 配置。两者将从同一个地方提供服务,但不能保证端口号或子域匹配。
想法 1:通过获取 window.location.host 并附加标准端口,尝试猜测 javascript 中的 BACKEND_URL 是什么。这很骇人听闻而且容易出错。
想法 2:将前端移至 Django 并使其询问 swampdragon 凭据(它们将在主页视图的上下文中发送)。问题在于,前端文件是由 grunt 编译的。所以 Django 会期待这样的东西:
<script src="{% static 'scripts/vendor/modernizr.js' %}"></script>
其实我有
<script src="scripts/vendor/a8bcb0b6.modernizr.js"></script>
其中 'a8bcb0b6' 是 grunt 的 hash/version 编号,将在下一个 minification/build 期间重新生成。我是否需要添加额外的逻辑来摆脱这些东西并将 grunt 的输出目录复制到 django 的静态和模板目录?
或者还有其他方法可以使这项工作,正确的方法,我错过了?
你的架构已经很干净了,不需要让 Django 知道 g运行t 或提供静态文件,也不需要使用 JS hacks 来猜测端口号
反向代理
使用 反向代理 像 nginx 或任何其他您喜欢的 Web 服务器作为静态文件 和 REST 的前端API.
In computer networks, a reverse proxy is a type of proxy server that retrieves resources on behalf of a client from one or more servers. These resources are then returned to the client as though they originated from the proxy server itself. (Wikipedia)
我将概述重要方面,但不会过多介绍细节:
URL 用于 REST API
我们进行配置,以便 nginx 将 API 请求转发给 Django
location /api {
proxy_pass http://127.0.0.1:8000; # assumes Django listens here
proxy_set_header Host $http_host; # preserve host info
}
所以上面假设你的 Django REST 被映射到端口 8000
上的 /api
和 运行s(例如你可以 运行 gunicorn 在那个端口上,或者任何您喜欢的其他服务器)
http://nginx.org/en/docs/http/ngx_http_proxy_module.html
URL 用于我们的前端应用程序
接下来 nginx 将提供来自 g运行t 的静态文件,只需将其指向静态文件夹
location / { alias /app/static/; }
以上假定您的静态资源位于 /app/static/
文件夹中(例如 index.html
、您的 CSS、JS 等)。所以这主要是为了加载您的 BackboneJS 应用程序。
Django 静态文件
下一步不是必需的,但如果您有与 Django 应用程序一起使用的静态文件(使用 ./manage.py collectstatic
生成的静态文件,例如 Django 管理员或 Django 的 UI REST Framework 等),只需根据您的 Django settings.py
STATIC_URL
和 STATIC_ROOT
location /static { alias /app/django_static_root/; }
/static
和django_static_root
分别是STATIC_URL
和STATIC_ROOT
总结
例如当你点击 example.com/
时,nginx 只是提供静态文件,然后当 JS 脚本对 /api
进行 REST 调用时,它会被困在 /api
nginx 位置并转发给 Django
最终结果是,example.com/
和 example.com/api
都访问了同一个前端 Web 服务器,该服务器将它们代理到正确的位置
好了,保留代理解决了您的端口和子域问题(以及许多其他问题,例如来自 Django 的缓慢静态文件和 Web 浏览器和防火墙中的同源策略,除了默认的 HTTP 和 HTTPS 端口外不喜欢任何东西)