如何部署连接到Django RESTful API的静态网站?

时间:2015-08-21 19:39:26

标签: django backbone.js gruntjs marionette

首先,google或SO搜索对我没有帮助:关于django静态文件的很多提示,我认为这些提示与此无关。

我继承了一个由以下项目组成的项目:

  • Django后端以API的形式返回JSON响应;
  • 标准Swampdragon部署将实时更新推送到前端;这里的配置很少;
  • Frontend webapp建立在Backbone和marionette.js上,由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的哈希/版本号,并将在下一次缩小/构建期间重新生成。我是否需要添加额外的逻辑来摆脱这些东西并将grunt的输出目录复制到django的静态和模板dirs?

还是有另一种方法可以使这项工作,正确的,我不知道了吗?

1 个答案:

答案 0 :(得分:1)

您的架构已经很干净,不需要让Django了解grunt或提供静态文件,也不需要使用JS hacks来猜测端口号

反向代理

使用反向代理(如nginx)或任何其他您喜欢的Web服务器作为静态文件 REST API的前端。

  

在计算机网络中,反向代理是一种代理服务器   代表客户端从一个或多个服务器检索资源。   然后将这些资源返回给客户端,就好像它们一样   源自代理服务器本身。 (维基百科)

我将概述重要方面,而不是过多详细说明:

REST API的URL

我们进行配置,以便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映射到/api并在端口8000上运行(例如,您可以在该端口上运行gunicorn,或者您喜欢的任何其他服务器)

http://nginx.org/en/docs/http/ngx_http_proxy_module.html

我们前端应用的网址

接下来nginx将通过简单地将其指向静态文件夹来提供来自grunt的静态文件

location / { alias /app/static/; }

以上假设您的静态资源位于/app/static/文件夹中(如index.html,您的CSS,JS等)。所以这主要是加载你的BackboneJS应用程序。

Django静态文件

下一步不是必需的,但是如果您有与Django应用程序一起使用的静态文件(使用./manage.py collectstatic生成的静态文件,例如django管理员或Django REST Framework的UI等),根据您的Django settings.py STATIC_URLSTATIC_ROOT

进行映射
location /static { alias /app/django_static_root/; }

/staticdjango_static_root分别是STATIC_URLSTATIC_ROOT

总结

所以,例如当你点击example.com/时,nginx只提供静态文件,然后当一个JS脚本对/api进行REST调用时,它会被困在/api nginx位置并被转发到Django < / p>

最终结果是,example.com/example.com/api都点击了相同的前端Web服务器,将它们代理到正确的位置

所以你有它,保留代理解决了你的端口和子域问题(以及许多其他问题,比如来自Django的慢速静态文件和web浏览器和防火墙中的同源策略,除了默认的HTTP和HTTPS端口之外不喜欢任何东西)