本文主要介绍为网站搭建后端时的技术选型考虑,以及通过写一个简单的HelloWorld接口快速了解前端和后端交互的流程。
文章目录
- 本系列前文传送门
- 一、场景说明
- 二、后端语言技术选型
- 三、后端框架技术选型
- Django 特点
- Flask 特点
- FastAPI 特点
- Tarnado 特点
- 四、用Flask先来个最简单的HelloWorld
- 五、在前端Vue中请求自己的接口
- 解决接口请求时的跨域问题 CORS policy
- 方法一:在服务器端开启CORS
- 方法二:在前端项目中设置代理
- 六、扩展出多个接口
在上一篇文章中我们介绍了网站的前后端分离,于是在我们有了前端项目之后,我们要来考虑搭建我们的后端项目。
使用哪种编程语言来作为后端语言可以有很多种考虑方式,基本上常见的主流语言都可以作为后端语言,主要根据立场和需求来选择。比如:
java
语言好招人;python
, PHP
, node.js
, ruby
等动态语言编写更加灵活,易上手;node.js
的情况下,有利于使用React
作为前端框架,这样基本整个网站的开发语言都可以统一在javascript
阵线上;ruby
和python
都有强大丰富的生态以及完善的工具框架;golang
;Rust
具备超高的安全性;这里我会选择python
作为后端语言(当然,我也非常推荐ruby
, PHP
和node.js
),理由主要如下:
python
拥有简洁易读的语法,容易上手。更重要的是,python
有丰富的生态,这使得在开发过程中有很多现成的工具或者解决方案来加快我的开发效率python
可能会被人诟病"性能差"不如静态语言。单纯从性能比较上可能确实如此,但是由于我们是开发后端项目,主要是跟前端项目通过网络请求的方式进行交互,在网络请求交互的背景下,编程语言本身性能的影响已经可以忽略。如果真的业务处理逻辑慢到影响整个请求过程,那么需要反思的不是编程语言本身,而是逻辑写太糟糕。在选定使用python
后,就需要考虑在python
丰富的生态中选择哪个框架来进行后端开发了。最常见的有Django
, Flask
, FastAPI
, tarnado
等等,同样是根据自己的需求结合不同框架各自的特点来选择:
Django
是一个非常完整的框架,当我们使用它来搭建项目的时候,只要按照文档一步一步进行配置和编写即可。而Django
会帮我们做好诸如架构设计、SQL保护之类的安全工作等等。
但与设计完备相对应的是,这意味着Django
开发会比较"重"。包括需要阅读文档来学习Django
开发模式的学习成本,以及项目对计算机资源消耗较大的机器成本。
对Django
对应的,Flask
是一个轻量级框架,当使用Flask
搭建项目时,可以简单到像我们写一个python
脚本一样,直接由一个.py
的短短几行代码编写并启动。另外就是Flask
非常灵活,或者说可以自由扩展或者定制化,丰富的生态提供的各类工具库能够让我们自由选择和搭配来满足实际业务需求。
而与灵活相对应的,就是Flask
需要自己进行Django
帮我们事先做好的事情,比如架构设计、文件和配置管理等等。
FastAPI
跟Flask
一样是轻量级框架,也体现了它名字里的Fast,并且从我个人角度,由于这个框架完全兼容了另一个我超喜欢的库pydantic
,pydantic
在做数据检验和模型设计的应用场景中十分好用,代码可以变得非常直观简洁并且有非常清晰的结构/流程,所以FastAPI
也是我非常推荐的框架。
Tornado
是一个Python
中的一个Web框架和异步网络库,通过使用非阻塞网络 I/O,Tornado
可以扩展到数万个开放连接,这使其成为长轮询、WebSocket 和其他需要与每个用户建立长期连接的应用程序的理想选择。
所以如果是面对高并发的场景,可以试试Tarnado
来实现接口。当然,其他框架也是有对应的工具可以实现异步操作的。
各个框架各有特点,当我们选择某一种框架的时候也可以从其他框架的做法上借鉴得到我们自己的解决方案,比如参考Django
的架构设计来组织我们的项目代码。
这里考虑到我们在这系列的文章里不会进行大规模的业务开发,所以选择轻量级框架,Flask
是在市场上比较广泛的轻量级框架,接下来的后端项目就使用Flask
进行开发和介绍。
就像使用vue
之前需要安装node.js
环境,使用Flask
之前也需要安装python
环境,可以根据自己的系统参考以下文章进行安装:
然后在命令行cmd
中运行如下命令进行Flask
安装:
pip install Flask
然后我们就可以开始写一个HelloWorld级别的项目了,首先创建一个helloworld.py
文件,然后写入如下代码:
from flask import Flask
app = Flask(__name__)
@app.route("/")
def hello_world():
return "Hello, World!
"
然后我们就可以运行如下命令启动Flask
项目:
flask --app helloworld run --port 5001
这里的--app
选项后面的值是我们入口文件的名称,这里就是helloworld
,--port
后面是指定端口值,不加--port
选项的话默认使用5000
端口。
于是我们就可以在浏览器中访问 Hello, World!127.0.0.1:5001
或者localhost:5001
来访问我们的页面,如下:
一个简易的接口就完成了,如果我们使用编程语言进行数据请求的话,就会得到我们在代码中返回的值"
我们在前后端分离的文章中已经介绍过如何在vue
中请求外部接口,当时我们是请求的公开API,于是现在我们搭建自己的后端项目后,可以换成自己的地址http://127.0.0.1:5001
,前端项目中HelloWorld.vue
代码变化如下:
如果我们回到浏览器页面会发现,我们并没有像预期一样从我们自己的接口得到数据,页面的内容部分是一片空白,如下:
这显然是渲染HelloWorld.vue
代码时出错了,我们F12打开调试工具查看console内容,可以看到如下报错信息:
Access to XMLHttpRequest at 'http://127.0.0.1:5001/' from origin 'http://localhost:8080' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.
这个错误信息提示我们,我们在前端js
代码中的请求被CORS(跨站资源共享)政策给拦截了。CORS(跨源资源共享)允许在网页中执行的 JavaScript XMLHttpRequest (XHR) 调用与来自非源域的资源进行交互。 CORS 是所有浏览器强制执行的同源策略的常用解决方案。
我们使用的后端框架是Flask
,所以为了让Flask
开启CORS,我们需要安装一个扩展库flask-cors
,运行如下命令进行安装:
pip install flask-cors
然后我们在flask
的入口代码中导入并开启CORS,代码变化如下:
这时候重启flask
项目然后回到浏览器刷新页面,已经可以看到前端项目成功请求到了数据:
其他不同服务器框架具体如何开启CORS,可以参考这份指南
首先到config/index.js
中修改代理配置,改动如下:
改完之后,我们就可以用请求/api
的方式请求http://127.0.0.1:5001
,(/api
类似于是http://127.0.0.1:5001
的别名或缩写)。于是我们回到HelloWorld.vue
中修改我们的请求地址,改动如下:
这时候回到浏览器刷新页面,已经可以看到前端项目同样成功请求到了数据:
现在我们希望除了title
之外,我们的posts
也是通过请求我们自己的接口获得,这相当于我们需要两个接口,一个返回title
,一个返回posts
。
为此我们在flask
的helloworld.py
中增加一个路由映射和返回逻辑来处理和返回数据,如下:
这时候我们访问http://127.0.0.1:5001/posts
可以这里变量posts
中的两条post。
然后我们修改HelloWorld.vue
中的getData()
方法如下:
methods: {
async getData() {
try {
// axios 获取数据方法
const res = await this.$http.get(
"/api"
);
this.title = res.data;
// // axios 获取数据方法
// const response = await this.$http.get(
// "http://jsonplaceholder.typicode.com/posts"
// );
// // JSON格式的返回值会自行解析
// this.posts = response.data;
// Fetch API 获取数据方法
// const response = await fetch("http://jsonplaceholder.typicode.com/posts");
const response = await fetch("/api/posts");
this.posts = await response.json();
} catch (error) {
console.log(error);
}
},
},
老样子,回到浏览器页面刷新,就可以看到页面如我们预期一样发生变化,如下:
至此我们已经完成了新扩展一个接口并返回一组数据的任务。需要注意的是,我们在flask
中可以用from flask import jsonify
导入flask
的jsonify
方法来替代我们刚才使用的json.dumps()
,如下:
@app.route("/posts")
def get_posts():
posts = [{
"userId": 10,
"id": 99,
"title": "temporibus sit alias delectus eligendi possimus magni",
"body": "quo deleniti praesentium dicta non quod\naut est molestias\nmolestias et officia quis nihil\nitaque dolorem quia"
}, {
"userId": 10,
"id": 100,
"title": "at nam consequatur ea labore ea harum",
"body": "cupiditate quo est a modi nesciunt soluta\nipsa voluptas error itaque dicta in\nautem qui minus magnam et distinctio eum\naccusamus ratione error aut"
}]
return jsonify(posts)
剩下的就是我们后端如何存储和处理数据了,我们如果数据量不大或者数据结构简单,可以直接把数据存成.json
文件,然后在代码中读取并处理。数据规模较大或者结构复杂,可以存到数据库中,然后由python
和flask
与数据库交互。
至此,一个网站的基本雏形已经形成了,接下来我们将进一步完善它。
写文不易,如果对你有帮助的话,来一波点赞、收藏、关注吧~