「网页开发|后端开发|Flask」08 python接口开发快速入门:技术选型写一个HelloWorld接口

news2024/11/14 21:27:23

本文主要介绍为网站搭建后端时的技术选型考虑,以及通过写一个简单的HelloWorld接口快速了解前端和后端交互的流程。

文章目录

  • 本系列前文传送门
  • 一、场景说明
  • 二、后端语言技术选型
  • 三、后端框架技术选型
    • Django 特点
    • Flask 特点
    • FastAPI 特点
    • Tarnado 特点
  • 四、用Flask先来个最简单的HelloWorld
  • 五、在前端Vue中请求自己的接口
    • 解决接口请求时的跨域问题 CORS policy
      • 方法一:在服务器端开启CORS
      • 方法二:在前端项目中设置代理
  • 六、扩展出多个接口

本系列前文传送门

  • 「网页开发|前端开发|Vue」01 快速入门:快速写一个Vue的HelloWorld项目
  • 「网页开发|前端开发|Vue」02 从单页面到多页面网站:使用路由实现网站多个页面的展示和跳转
  • 「网页开发|前端开发|页面布局」03 学会够用的CSS,实现任意你想要的页面布局
  • 「网页开发|前端开发|Vue」04 快速掌握开发网站需要的Vue基础知识
  • 「网页开发|前端开发|Vue」05 Vue实战:从零到一实现一个网站导航栏
  • 「网页开发|前端开发|Vue」06 公共组件与嵌套路由:让每一个页面都平等地拥有导航栏
  • 「网页开发|前端开发|Vue」07 前后端分离:如何在Vue中请求外部数据

一、场景说明

在上一篇文章中我们介绍了网站的前后端分离,于是在我们有了前端项目之后,我们要来考虑搭建我们的后端项目。

二、后端语言技术选型

使用哪种编程语言来作为后端语言可以有很多种考虑方式,基本上常见的主流语言都可以作为后端语言,主要根据立场和需求来选择。比如:

  • 作为公司来考虑,使用java语言好招人;
  • 使用python, PHP, node.js, ruby等动态语言编写更加灵活,易上手;
  • 在使用node.js的情况下,有利于使用React作为前端框架,这样基本整个网站的开发语言都可以统一在javascript阵线上;
  • rubypython都有强大丰富的生态以及完善的工具框架;
  • 天生高并发的golang
  • 新时代的C语言Rust具备超高的安全性;

这里我会选择python作为后端语言(当然,我也非常推荐ruby, PHPnode.js),理由主要如下:

  • 我这里是从个人开发的角度出发,python拥有简洁易读的语法,容易上手。更重要的是,python有丰富的生态,这使得在开发过程中有很多现成的工具或者解决方案来加快我的开发效率
  • python可能会被人诟病"性能差"不如静态语言。单纯从性能比较上可能确实如此,但是由于我们是开发后端项目,主要是跟前端项目通过网络请求的方式进行交互,在网络请求交互的背景下,编程语言本身性能的影响已经可以忽略。如果真的业务处理逻辑慢到影响整个请求过程,那么需要反思的不是编程语言本身,而是逻辑写太糟糕。

三、后端框架技术选型

在选定使用python后,就需要考虑在python丰富的生态中选择哪个框架来进行后端开发了。最常见的有Django, Flask, FastAPI, tarnado等等,同样是根据自己的需求结合不同框架各自的特点来选择:

Django 特点

Django是一个非常完整的框架,当我们使用它来搭建项目的时候,只要按照文档一步一步进行配置和编写即可。而Django会帮我们做好诸如架构设计、SQL保护之类的安全工作等等。

但与设计完备相对应的是,这意味着Django开发会比较"重"。包括需要阅读文档来学习Django开发模式的学习成本,以及项目对计算机资源消耗较大的机器成本。

Flask 特点

Django对应的,Flask是一个轻量级框架,当使用Flask搭建项目时,可以简单到像我们写一个python脚本一样,直接由一个.py的短短几行代码编写并启动。另外就是Flask非常灵活,或者说可以自由扩展或者定制化,丰富的生态提供的各类工具库能够让我们自由选择和搭配来满足实际业务需求。

而与灵活相对应的,就是Flask需要自己进行Django帮我们事先做好的事情,比如架构设计、文件和配置管理等等。

FastAPI 特点

FastAPIFlask一样是轻量级框架,也体现了它名字里的Fast,并且从我个人角度,由于这个框架完全兼容了另一个我超喜欢的库pydanticpydantic在做数据检验和模型设计的应用场景中十分好用,代码可以变得非常直观简洁并且有非常清晰的结构/流程,所以FastAPI也是我非常推荐的框架。

Tarnado 特点

Tornado 是一个Python中的一个Web框架和异步网络库,通过使用非阻塞网络 I/O,Tornado 可以扩展到数万个开放连接,这使其成为长轮询、WebSocket 和其他需要与每个用户建立长期连接的应用程序的理想选择。

所以如果是面对高并发的场景,可以试试Tarnado来实现接口。当然,其他框架也是有对应的工具可以实现异步操作的。


各个框架各有特点,当我们选择某一种框架的时候也可以从其他框架的做法上借鉴得到我们自己的解决方案,比如参考Django的架构设计来组织我们的项目代码。

这里考虑到我们在这系列的文章里不会进行大规模的业务开发,所以选择轻量级框架,Flask是在市场上比较广泛的轻量级框架,接下来的后端项目就使用Flask进行开发和介绍。

四、用Flask先来个最简单的HelloWorld

就像使用vue之前需要安装node.js环境,使用Flask之前也需要安装python环境,可以根据自己的系统参考以下文章进行安装:

  • Windows 安装Python环境
  • Linux 安装Python环境

然后在命令行cmd中运行如下命令进行Flask安装:
pip install Flask

然后我们就可以开始写一个HelloWorld级别的项目了,首先创建一个helloworld.py文件,然后写入如下代码:

from flask import Flask

app = Flask(__name__)

@app.route("/")
def hello_world():
    return "<p>Hello, World!</p>"

然后我们就可以运行如下命令启动Flask项目:
flask --app helloworld run --port 5001

这里的--app选项后面的值是我们入口文件的名称,这里就是helloworld--port后面是指定端口值,不加--port选项的话默认使用5000端口。

于是我们就可以在浏览器中访问127.0.0.1:5001或者localhost:5001来访问我们的页面,如下:
在这里插入图片描述
一个简易的接口就完成了,如果我们使用编程语言进行数据请求的话,就会得到我们在代码中返回的值"<p>Hello, World!</p>"

五、在前端Vue中请求自己的接口

我们在前后端分离的文章中已经介绍过如何在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 是所有浏览器强制执行的同源策略的常用解决方案。

解决接口请求时的跨域问题 CORS policy

方法一:在服务器端开启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

为此我们在flaskhelloworld.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导入flaskjsonify方法来替代我们刚才使用的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文件,然后在代码中读取并处理。数据规模较大或者结构复杂,可以存到数据库中,然后由pythonflask与数据库交互。

至此,一个网站的基本雏形已经形成了,接下来我们将进一步完善它。

写文不易,如果对你有帮助的话,来一波点赞、收藏、关注吧~👇

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1014384.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Gin 打包vue或react项目输出文件到程序二进制文件

Gin 打包vue或react项目输出文件到程序二进制文件 背景解决方案1. 示例目录结构2. 有如下问题要解决:3. 方案探索 效果 背景 前后端分离已成为行业主流&#xff0c;vue或react等项目生成的文件独立在一个单独目录&#xff0c;与后端项目无关。 实际部署中&#xff0c;通常前面套…

Scrum敏捷开发端到端管理流程

Leangoo领歌是Scrum中文网&#xff08;scrum.cn&#xff09;旗下的一款永久免费的敏捷研发管理工具。 Leangoo领歌覆盖了敏捷研发全流程&#xff0c;它提供端到端敏捷研发管理解决方案&#xff0c;包括小型团队敏捷开发&#xff0c;规模化敏捷SAFe&#xff0c;Scrum of Scrums…

父子进程区别与GDB多进程调试

父子进程之间的关系&#xff1a; 区别&#xff1a; 1.fork()函数的返回值不同&#xff0c;父进程中&#xff1a;>0 返回的子进程ID 子进程中&#xff1a;ID0 2.pcb中的数据有区别&#xff0c;当前进程的id pid &#xff0c;当前父进程的id ppid&#xff0c;信号集 共同点…

黑马头条 后端项目部署_持续集成 Jenkins配置

项目部署_持续集成 1 今日内容介绍 1.1 什么是持续集成 持续集成&#xff08; Continuous integration &#xff0c; 简称 CI &#xff09;指的是&#xff0c;频繁地&#xff08;一天多次&#xff09;将代码集成到主干 持续集成的组成要素 一个自动构建过程&#xff0c; 从检出…

如何在RK3568开发板上实现USBNET?——飞凌嵌入式/USB Gadget/USB-NET/网络

本文将借助飞凌嵌入式OK3568-C开发板为大家介绍实现USBNET模式的方法&#xff0c;在这之前需要先知道什么是USB Gadget——USB Gadget是指所开发的电子设备以USB从设备的模式通过USB连接到主机。举个例子&#xff1a;将手机通过USB线插入PC后&#xff0c;手机就是USB Gadget。同…

【IP数据报】IP地址和MAC地址的区别

1、用IP地址来标识Internet的主机 在每个IP数据报中&#xff0c;都会携带源IP地址和目标IP地址来标识该IP数据报的源和目的主机。IP数据报在传输过程中&#xff0c;每个中间节点(IP 网关)还需要为其选择从源主机到目的主机的合适的转发路径(即路由)。IP协议可以根据路由选择协…

Android Update Engine 分析(十九)Extent 到底是个什么鬼?

文章目录 0. 导读1. 什么是 Extent?1. 什么是 Extent?2. Wikipedia 中的解释3. Ext4 中的 Extent2. Android OTA 中的 Extent2.1 update_metadata.proto 中的 Extent2.2 update engine 代码中的 Extentpayload_consumer 中的 Extentpayload_generator 中的 Extent2.3 OTA 中的…

Shell 正则表达式及综合案例及文本处理工具

目录 一、常规匹配 二、常用特殊字符 三、匹配手机号 四、案例之归档文件 五、案例之定时归档文件 六、Shell文本处理工具 1. cut工具 2. awk工具 一、常规匹配 一串不包含特殊字符的正则表达式匹配它自己 例子&#xff0c;比如说想要查看密码包含root字符串的&#x…

【华为云云耀云服务器L实例评测|云原生】自定制轻量化表单Docker快速部署云耀云服务器

&#x1f935;‍♂️ 个人主页: AI_magician &#x1f4e1;主页地址&#xff1a; 作者简介&#xff1a;CSDN内容合伙人&#xff0c;全栈领域优质创作者。 &#x1f468;‍&#x1f4bb;景愿&#xff1a;旨在于能和更多的热爱计算机的伙伴一起成长&#xff01;&#xff01;&…

发现某设备 adb shell ps 没有输出完整信息

某错误示例 并不是都使用 -ef 参数查找都能够返回完整信息&#xff0c;某些版本设备不适用 -ef 也不会返回完整信息。 简单兼容 简单兼容不同版本 Android 设备查找进程列表&#xff0c;没有通过脚本判断 Android 版本&#xff0c;如有兴趣可以自己修改。 :loop adb shell…

代码配置仓库GitLab安装部署

Github是目前世界上代码行数最多的在线软件版本配置库平台&#xff0c;而Gitlab是Github对应的开源版本&#xff0c;本文主要描述Gitlab的安装部署。 https://about.gitlab.com/ https://gitlab.cn/install/ 如上所示&#xff0c;从官方网站中下载不同操作系统的版本&#xf…

聚合物发光材料荧光量子效率测量

近年来‚聚合物发光材料与器件受到人们的极大关注和高度重视‚其关键是聚合物发光器件具有光吸收范围宽‚吸收强度大‚发光效率高‚激发阈值低以及制备工艺简便灵活等显著特点‚已成为有机固体激光领域一个新的研究热点。 现有的聚合物发光材料体系主要集中在&#xff1a;聚噻…

04-Flask-新版Flask运行方式

新版Flask运行方式 前言老版本运行方式新版本运行方式命令行方式运行pycharm运行 前言 本篇来学习下新版Flask运行方式 老版本运行方式 app.run()&#xff1a;1.0之前版本 # -*- coding: utf-8 -*- # Time : 2023/9/16 # Author : 大海# 导入flask from flask import F…

react路由02——react-routerV6 中路由表的使用(useRoutes钩子)

react路由02——react-routerV6 中路由表的使用&#xff08;useRoutes钩子&#xff09; 1. 不使用路由表1.1 关于react-routerV6路由简单使用1.2 未配置路由表 2. 路由表——useRoutes钩子2.1 配置路由表2.2 一级路由组件——useRoutes钩子2.3 二级路由组件——Outlet组件2.4 目…

进化算法、遗传编程和学习

一、说明 进化算法是一系列搜索算法&#xff0c;其灵感来自自然界&#xff08;达尔文主义&#xff09;进化过程。所有不同家庭成员的共同点是&#xff0c;通过应用受自然遗传学和自然选择启发的 算子&#xff0c;通过进化出最初 随机的候选解决方案群体来解决问题&#…

打包发布异常01

缺一不可 Build starting... Start: Fri Sep 15 08:07:01 UTC 2023 bfdf11d63b70 Git: 0.33-0-g6190381 commit 61903816b88ff5cf3e0848cd19fcb190af0801cd Author: 米伟强 Date: Fri Sep 15 15:57:28 2023 0800gradle插件版本Init SDKMan Found Android manifest Android …

Rust :与C交互

rust调用C端的库函数&#xff0c;有很多方法。今天介绍通过cc库的方式&#xff0c;实现rust调用c端库函数。 1、相关准备&#xff1a; 在ffi目录下&#xff0c;创建了c_part和rust_ffi文件夹。 c_part下放了ctools.c文件&#xff0c;里面有一些库函数&#xff0c;需要让rust调…

华为云云耀云服务器L实例评测|基于Docker环境快速部署Halo个人博客实操

目录 一、基本介绍 1.1 云耀云服务器L实例介绍 1.2 实操介绍 二、云耀云服务器的购买及基本使用 2.1 服务器购买流程 2.2 初始化连接流程 2.3 系统环境检查 三、Docker中运行Halo 3.1 Halo基本介绍 3.2 Docker的安装 3.3 使用 Docker 镜像创建容器 四、安装初始化H…

LVS负载均衡DR直接路由

LVS负载均衡DR直接路由 一、DR工作原理二、 数据包流向三、DR模式特点四、ARP问题4.1第一次访问完整&#xff08;不考虑实际问题&#xff09;4.2问题一&#xff1a;IP 地址冲突 五、部署LVS-DR集群5.2、第一台web服务器5.3、第二台Web节点服务器5.4、在客户机测试&#xff08;1…

QT : 仿照QQ 完成弹出登录窗口,并实例化组件

1. 运行效果图 2. Headers #ifndef MAINWINDOW_H #define MAINWINDOW_H#include <QMainWindow>class MainWindow : public QMainWindow {Q_OBJECTpublic:MainWindow(QWidget *parent nullptr);~MainWindow(); }; #endif // MAINWINDOW_H 3. mainWindow.cpp &#xff1a…