前言:本次尝试源于我们内部的一个项目,由于前端逻辑比较复杂,就打算将前后端分开来开发。由于之前用Django开发过软件,对AngularJS(Angular 1.0版)也有一定的了解,因此就将技术路线锁定在了这两个开源工具上,用Angular做前端(这次是Angular 2),Django做后端。

这个系列计划分为以下四个部分:

(1): 分离 or 不分离,it's the question

(2):前端组件化——Angular

(3):后端服务化——Django REST框架

(4):前后端的通信——跨域请求

前后端的关系


前后端是否分离是我们设计网站应用程序架构时需要想清楚的首要问题。这直接影响了我们的开发流程,技术路线,甚至后期的维护。

要搞清楚是否需要分离,首先要明白前后端各自最主要的职责是什么。

关于前端

  • 之所以叫做前端,是因为相对于服务器端,这部分是直接与用户接触的;
  • 前端三件宝:html, css, JavaScript;
  • 主要职责:负责网站内容的展示,接受用户的输入并作出相应的反馈(包括用户输入有效性的验证,将输入的数据传给服务器,接受服务器传回的数据并作出正确反应);

关于后端

  • 对前端的请求作出响应;
  • 数据的验证(再次验证);
  • 数据的预处理和分析(可以调用系统资源);
  • 数据的持久化(保存到数据库或文件系统);
  • 当然还有很多其他的功能,例如保存负载均衡等,但是最重要的一个工作是为前端提供数据;
  • 后端的开发语言比前端的选择空间大得多,例如Java、Ruby,PHP等,当然还有Python.
总的来说,前端可以看做是数据的消费者(当然也可以是数据的来源),后端则可以看成是数据的生产者(来源于数据库或对输入数据的加工)。那么如何判断前后端是否分离了呢,这个问题的核心在什么地方呢?
其实就在于模板的与数据结合的位置,以及,模板的控制权在谁手里。
 
 

不分离的情况


之前用Django开发软件时,并没有深刻的感受到Django在网站开发上作为一个框架的完美主义(大包大揽)。最近回顾之前做的一些工作时,才发现了这一事实。利用Django,不用分离出前端,也可以做出非常棒的网站。因为Django中自带开发一个网站的全部要素——基本配置、路由、视图、模型,表单,模板,模板的渲染等。

如果前后端放在一起,使用Django的模板系统(模板的控制权在后端),这样做最大的好处就是数据可以从前端的表单(Form)直接提交给后端的视图函数(View function);数据在视图函数中经过处理后可以直接传递给模板(template),最终将渲染后的模板展示给用户。在这个过程中,数据流如下:

html -> Python -> (JavaScript) -> html
  • html -> Python:通常情况下,是从html接受表单的输入,然后使用PUT或POST方法直接提交给Django的视图函数;
  • Python -> JavaScript:数据经过视图函数的处理,最后可以转换成JSON格式传递给JS;
  • JavaScript -> html:由JS进一步处理后的数据可以通过对html中DOM的操作反映到前端,也可以使用一些前端框架(例如AngularJS的双向绑定)将数据传给html;
  • Python -> html:数据也可以经过视图函数处理后,直接传给模板(JSON格式或由字典构成的数组),在模板中可以使用{{ data }}这种格式直接消费视图函数传递的数据。

在整个过程中,数据的交换都是同源的,这样操作方便,安全性也高。同源就是指http请求之间的协议、域名和端口都相同。

此时模板的控制权和数据与模板的结合位置都在后端。

当需要分离时。。。


前后端统一有很多好处,开发起来也省时省力。那么在什么情况下需要分离呢?

  • 前端逻辑比较复杂;
  • 对UI的要求比较高(并不是说Django的模板丑,而是自己的css技术不够);
  • 提高代码的可维护性和可扩展性;

分离之后,Django就不用处理模板的渲染,路由这些事务了。后端专注于提供数据,更重要的职责是维护系统架构的稳定,保证数据的安全。前端人员专注于交互,快速响应UI的变化。

程序的结构

分离前程序其实就是一个单一的Django程序,一切基本上都可以用Django搞定。但是分离之后,Django就只负责后端的数据,前端就完全不由它管了。如果前端使用Angular,那么此时就相当于有两个程序:前端的Angular程序,后端的Django程序。那么问题就来了,这两个程序之间怎么交换数据呢?这时候有一个方法就是将后端设计成REST(Representational State Transfer,又称具象状态传输)结构。

此外还有一个问题需要解决,分离前数据是在同一个程序内部传递的,属于同源传递,这是浏览器默认就支持的行为;但是分离后,数据需要在两个不同的程序之间传递,这两个程序必定是不同源的,至少是端口不同,为了安全方面的考虑,这样的操作是被限制的。这时就需要解决跨源资源请求的问题,现在用的比较多的是CORS(Cross-Origin Resource Sharing,跨源资源分享)。

图1:前后端分离后,它们通过http协议进行通信

如图1所示,前后端分离后,客户端通过http协议,使用GET、POST、PUT、DELETE等动词对资源发出请求(Request);服务器端收到请求后,完成相应的操作或通过http协议返回客户端需要的资源(Response)。

具象状态传输,REST


REST(Representational State Transfer,又称具象状态传输)是Roy Thomas Fielding博士于2000年在他的博士论文中提出来的一种万维网软件架构风格,目的是便于不同软件/程序在网络(例如互联网)中互相传递信息。目前在三种主流的Web服务实现方案中,因为REST模式与复杂的SOAP和XML-RPC相比更加简洁,越来越多的web服务开始采用REST风格设计和实现。

需要注意的是,REST是设计风格而不是标准。REST通常基于使用HTTP,URI,和XML以及HTML这些现有的广泛流行的协议和标准。

要理解什么是REST,我们需要理解下面几个概念:

  • 资源(Resources):REST是"表现层状态转化",其实它省略了主语。"表现层"其实指的是"资源"的"表现层"。那么什么是资源呢?就是我们平常上网访问的一张图片、一个文档、一个视频等。这些资源我们通过URI来定位,也就是一个URI(Uniform Resource Identifier,统一资源标志符)表示一个资源。
  • 表现层(Representation):资源是一个具体的实体信息,可以有多种的展现方式。而把实体展现出来就是表现层,例如一个txt文本信息,他可以输出成html、json、xml等格式,一个图片也可以jpg、png等方式展现,这个就是表现层的意思。URI确定一个资源,但是如何确定它的具体表现形式呢?应该在HTTP请求的头信息中用Accept和Content-Type字段指定,这两个字段才是对"表现层"的描述。
  • 状态转化(State Transfer):访问一个网站,就代表了客户端和服务器的一个互动过程。在这个过程中,肯定涉及到数据和状态的变化。而HTTP协议是无状态的,那么这些状态肯定保存在服务器端,所以如果客户端想要通知服务器端改变数据和状态的变化,肯定要通过某种方式来通知它。客户端能通知服务器端的手段,只能是HTTP协议。具体来说,就是HTTP协议里面,四个表示操作方式的动词:GET、POST、PUT、DELETE。它们分别对应四种基本操作:GET用来获取资源,POST用来新建资源(也可以用于更新资源),PUT用来更新资源,DELETE用来删除资源,如图2所示。

综合上面的解释,总结一下什么是RESTful架构:

(1)每一个URI代表一种资源;
(2)客户端和服务器之间,传递这种资源的某种表现层;
(3)客户端通过四个HTTP动词,对服务器端资源进行操作,实现"表现层状态转化"(对于浏览器前的用户来说就是,对界面的操作得到了恰当的反馈)。

图2:客户端通过http协议中的几个动词对资源进行操作

REST架构风格最重要的架构约束有6个:

  • 客户-服务器(Client-Server):通信只能由客户端单方面发起,表现为请求-响应的形式。

  • 无状态(Stateless):通信的会话状态(Session State)应该全部由客户端负责维护。

  • 缓存(Cache):响应内容可以在通信链的某处被缓存,以改善网络效率。

  • 统一接口(Uniform Interface):通信链的组件之间通过统一的接口相互通信,以提高交互的可见性。

  • 分层系统(Layered System):通过限制组件的行为(即每个组件只能“看到”与其交互的紧邻层),将架构分解为若干等级的层。

  • 按需代码(Code-On-Demand,可选):支持通过下载并执行一些代码(例如Java Applet、Flash或JavaScript),对客户端的功能进行扩展。

跨域资源共享,CORS


CORS是一个W3C标准,全称是"跨域资源共享"(Cross-origin resource sharing)。它允许浏览器向跨源服务器,发出XMLHttpRequest请求,从而克服了AJAX只能同源使用的限制。

实现条件

CORS需要浏览器和服务器同时支持。目前,所有浏览器都支持该功能,IE浏览器不能低于IE10。
整个CORS通信过程,都是浏览器自动完成,不需要用户参与。对于开发者来说,CORS通信与同源的AJAX通信没有差别,代码完全一样。浏览器一旦发现AJAX请求跨源,就会自动添加一些附加的头信息,有时还会多出一次附加的请求,但用户不会有感觉。因此,实现CORS通信的关键是服务器。只要服务器实现了CORS接口,就可以跨源通信。

在Django中的实现

在Django中,需要安装一个包来支持CORS操作,django-cors-headers可以帮我们添加需要的头信息,从而让Django支持跨域资源共享。具体可以参考django-cors-headers的官方文档。本文也会在后面详细介绍。

接下来会介绍Angular... 敬请期待。

Reference


https://zh.wikipedia.org/wiki/REST

https://github.com/astaxie/build-web-application-with-golang/blob/master/zh/08.3.md

http://www.ruanyifeng.com/blog/2016/04/cors.html

https://github.com/ottoyiu/django-cors-headers

记Angular与Django REST框架的一次合作(1):分离 or 不分离,it's the question的更多相关文章

  1. 记Angular与Django REST框架的一次合作(2):前端组件化——Angular

    注:这是这个系列的第二部分,主要集中在Angular的使用方面.之前使用过AngularJS(Angular 1.x),混在Django的模板中使用,这些页面一般完全是结果展示页.在有Django表单 ...

  2. Jhipster 一个Spring Boot + Angular/React 全栈框架

    Jhipster     一个Spring Boot + Angular/React 全栈框架: https://www.jhipster.tech/

  3. 教程:Visual Studio 中的 Django Web 框架入门

    教程:Visual Studio 中的 Django Web 框架入门 Django 是高级 Python 框架,用于快速.安全及可扩展的 Web 开发. 本教程将在 Visual Studio 提供 ...

  4. Django—— 缓存框架

    译者注:1.无用的,吹嘘的说辞不翻译:2.意译,很多地方不准确. 动态网站最为重要的一点就是好,网页是动态的.每一次用户请求页面,网站就要进行各种计算——从数据库查询,到render模板,到各种逻辑运 ...

  5. [oldboy-django][1初始django]web框架本质 + django框架 + ajax

    web框架本质 浏览器(socket客户端) - 发送请求(ip和端口,url http://www.baidu.com:80/index/) - GET 请求头(数据请求行的url上: Http1. ...

  6. 理解django的框架为何能够火起来

    理解django的框架为何能够火起来 https://www.yiibai.com/django/django_basics.html https://code.ziqiangxuetang.com/ ...

  7. Django ContentTypes框架使用场景

    Django contenttypes是一个非常有用的框架,主要用来创建模型间的通用关系(generic relation).不过由于其非常抽象, 理解起来并不容易.当你创建一个django项目的时候 ...

  8. Linux(CentOS7)系统中部署Django web框架

    1. 概述 部署django和vue架在逻辑上可以分为web层与数据库层:web前端通过实现了WSGI协议的模块对python代码进行解析,而python代码中则通过特定于数据库的操作接口对数据库进行 ...

  9. Python的Django REST框架中的序列化及请求和返回

    Python的Django REST框架中的序列化及请求和返回 序列化Serialization 1. 设置一个新的环境 在我们开始之前, 我们首先使用virtualenv要创建一个新的虚拟环境,以使 ...

随机推荐

  1. 你的MySQL服务器开启SSL了吗?

    最近,准备升级一组MySQL到5.7版本,在安装完MySQL5.7后,在其data目录下发现多了很多.pem类型的文件,然后通过查阅相关资料,才知这些文件是MySQL5.7使用SSL加密连接的.本篇主 ...

  2. android的drawable资源

    1.android中可以通过xml文件配置资源,比如字符串啦,整数拉.浮点数等等,当然也可以配置图片资源和选择器,下面我们就看看几种图片资源的配置. @1矩形方框,带渐变色的配置代码 <?xml ...

  3. select onchagnge 弹出自己的文本值

    select onchagnge 弹出自己的文本值onchange='alert($("option:selected",this).text())'

  4. BeanUtils.copyProperties VS PropertyUtils.copyProperties

    作为两个bean属性copy的工具类,他们被广泛使用,同时也很容易误用,给人造成困然:比如:昨天发现同事在使用BeanUtils.copyProperties copy有integer类型属性的bea ...

  5. 如何使程序运行在UI线程

    context.runOnUiThread(new Runnable() { @Override public void run() { _prop = new Prop(buyType, money ...

  6. 【css技能提升】css高级技巧

    本文是一个帮你提升 CSS 技巧的收藏集. 使用CSS复位 CSS复位可以在不同的浏览器上保持一致的样式风格.您可以使用CSS reset 库Normalize等,也可以使用一个更简化的复位方法: * ...

  7. solr的基本概念

    一.solr的基本概念 大家可以把solr搜索引擎看成一个数据库,不过是基于内存的.它可以存储信息,并且根据你的查询条件返回你想要的信息. 1.collection和core的概念 collectio ...

  8. 这个类复制文本文件FileCopy

    package JBJADV003; import java.io.File;import java.io.BufferedReader;import java.io.BufferedWriter;i ...

  9. 【Linux相识相知】bash的基础特性

    命令历史 shell进程会记录用户提交执行过的命令 可以是用history查看: [root@localhost dev]# history ss -tnl ifconfig vi /etc/sysc ...

  10. DELPHI XE5安装

    1.安装XE5 2. HNFJ-DPADCW-BDWCFU-FPNN QDF4-CTSDHV-RDFCFE-FEAN HNFK-BCN8NN-78N53D-H4RS 破解补丁使用方法: (1).复制压 ...