后端框架flask学习小记[通俗易懂]

2022-09-08 11:04:28 浏览数 (1)

大家好,又见面了,我是你们的朋友全栈君。

1. 写在前面

最近在和几个伙伴尝试搭建一个新闻推荐系统, 算是一个推荐算法的实战项目, 里面涉及到了前后端交互, 该项目里面,使用了Flask作为后台框架, 为了理清楚整个系统的交互,所以就快速参考着资料学习了下flask, 主要还是参考伙伴们写的flask简介和基础的内容, 加上了一些其他理解和实验辅助, 整理一篇心得文章, 算是flask初步入门。

对于一个算法工程师来讲,后端这块虽然不必详细弄清楚原理,但学习一些开发相关知识还是有好处的,因为在实际工作中经常会调试线上的代码调用策略或者模型,我们至少得弄明白,我们的数据流, 模型流到底是怎么走的, 整个系统从输入到最终输出是怎么运行的,这样才能运筹帷幄,从一个更高的角度去看待问题。

好吧,有点扯远了, 本篇文章主要介绍flask,这里依然是从使用的角度整理(因为我对原理也不清楚哈哈), 先不管那么多,会用就行, flask简单的来讲, 就是一个后端框架,基于python语言编写,比较容易上手,或者说不用懂太多细节就能写代码, 把前端传过来的请求,通过编写一些函数进行处理,然后返回给前端。 这里为了更好的理解,我会用一个非常简单的例子贯穿整个流程。 当然,如果想看稍微高大上点的代码,也可以去我们写的fun-rec项目,看新闻推荐系统的代码, 那个是vue-flask交互配合的,更加高级些。

所以,最简单的整个流程就是, 我们在前端页面上输入信息,发送请求给后端(flask), flask根据我们传过来的请求,去找到相应的函数去处理我们的请求(路由), 然后函数处理的结果封装起来返回给前端展示。 这次,主要是看看请求传过来之后,后端这个怎么找函数处理以及返回回去。

主要内容:

  • 先配置环境,安装flask
  • 路由 – 去找函数处理请求
  • 请求、响应和会话
  • 重定向与错误处理
  • 前端简单制作form表单 – 准备交互
  • 介绍两款工具(数据库操作API(sqlarchemy)和接口测试工具(Postman))
  • 小例子打通前后端交互流程
  • 新闻推荐系统vue和flask是怎么联系起来的呢?

Ok, let’s go!

2. 先配置环境,安装flask

这个不用多整理, flask在python里面也是一个包的形式存在,所以我们如果事先安装好了anaconda, 建立了虚拟环境,那么就直接可以

代码语言:javascript复制
pip install flask

然后输入下面代码测试下:

代码语言:javascript复制
from flask import Flask
app = Flask(__name__)

@app.route('/')   # 这个根目录,就是127.0.0.1:5000进入的位置
def hello_world():
	return "hello world"

if __name__ = '__main__':
	app.run()

如果正常的话,界面会显示hello world。其实,这就简单的走了一遍小流程(输入网址,根据路由到了hello_word函数,返回结果给前端)。

Flask将(name)作为参数,即Flask在当前模块运行,route()函数是一个装饰器,将请求的url映射到对应的函数上。上述代码将’/’与hello_world()函数进行绑定,因此在请求localhost:5000时,网页显示 Hello World 结果。

这里有几个关键点: 导包, 建立app(Flask(__name__)),路由匹配(@app.route())以及启动(app.run())。 几乎在写每个后端处理之前,这几个先写上再说。

程序的启动是用过Flask类的run()方法在本地启动服务器应用程序

代码语言:javascript复制
app.run(host, port, debug, options)

# 允许服务器被公开访问
app.run(debug=True, host='0.0.0.0', port=3000, threaded=True)
# 只能被自己的机子访问
# app.run(debug=True, host='127.0.0.1', port=10086, threaded=True)

这几个参数的描述如下:

安装这块比较简单,先这样。

3. 路由 – 去找函数处理请求

web界面输入一个网址,点击回车, 其实是访问的web服务器,然后服务器把结果返回到前端。 这个过程中有个匹配url的过程, 就是flask路由。

Flask中,路由是指用户请求的URL与视图函数之间的映射。Flask通过利用路由表将URL映射到对应的视图函数,根据视图函数的执行结果返回给WSGI服务器。

路由表的内容是由开发者进行填充, 主要有以下两个方式:

route装饰器: 使用Flask应用实例的route装饰器,将一个URL规则绑定到一个视图函数上

代码语言:javascript复制
# 通过装饰器的方式, Flask框架会将URL规则绑定到test()函数上, 这个很好用
@app.route('/test')       # 浏览器访问的时候,输入的url是127.0.0.1/test
def test():
	return 'this is response of test function'

add_url_rule() :该方法直接会在路由表中注册映射关系。其实route装饰器内部也是通过调用add_url_rule()方法实现的路由注册

代码语言:javascript复制
def test():
  return 'this is response of test function.'
app.add_url_rule('/test',view_func=test)

我习惯看第一种方式, 感觉比较帅。

3.1 指定HTTP方法

默认情况下, Flask的路由支持HTTP的GET请求, 如果需要试图函数支持HTTP的其他方法, 可以通过methods关键字参数进行设置。 关键字参数methods的类型为list, 可以同时指定多种HTTP方法。

代码语言:javascript复制
# 接收post和get请求, 如果不指定的话,就是get请求, 此时如果提交post请求是捕捉不到的
@app.route('/user', methods = ['POST', 'GET'])   
def get_users():
  if request.method == 'GET':
    return ... # 返回用户列表
  else:
    return ... # 创建新用户

这里先说下这两种请求的区别:

  • GET把参数包含在URL中, 也就是直接输入网址访问, 把参数放到这个网址里面去的时候,访问的就是get请求
  • POST通过request body传递参数, 采用表单的时候往往就是这个。 关于这个,后面测试接口的时候,会通过Postman进行演示。

这样就完成了最基本的功能, 当然,你说, 这个URL(/user)是写死的目前,如果我不确定怎么办呢? 比如, 我可能这个用户是某某, 而不同的某某,可能有不同的执行操作,这时候,就可以使用动态URL。

3.2 动态URL

动态URL用于当需要将同一类URL映射到同一个视图函数处理,比如,使用同一个视图函数 来显示不同用户的个人信息。那么可以将URL中的可变部分使用一对小括号<>声明为变量, 并为视图函数声明同名的参数:

代码语言:javascript复制
@app.route('/user/<uname>')   # <>提取参数用的
def get_userInfo(uname):
  return '%s's Informations' % uname


# 输入网址127.0.0.1/user/wuzhongqiang wuzhongqiang's Informations
# 输入网址127.0.0.1/user/zhangsan zhangsan's Informations

除了上述方式来设置参数,还可以在URL参数前添加转换器来转换参数类型: 前端本身默认是传入过来的是字符串格式,如果感觉本身传入的参数不应该是字符串格式的,那就可以在URL参数前添加转换器转换参数类型

代码语言:javascript复制
@app.route('/user/<int:uname>')   # <int: name> int 是一个转换器
def get_userInfo(uname):
    return '%s's Informations' % uname

使用该方法时,请求的参数必须是属于int类型,否则将会出现404错误。目前支持的参数类型转换器有int, float, string, path。后两者的区别是path里面可以有

为了满足一个视图函数可以解决多个问题,因此每个视图函数可以配置多个路由规则

代码语言:javascript复制
@app.route('/user')
@app.route('/user/<uname>')
@app.route('/user/<int:uname>')
def get_userInfo(uname=None):
    if uname:
    	return '%s's Informations' % uname
    else:
        return 'this is all informations of users'

3.3 自定义匹配规则

当然,这里也可以自定义一些规则,去进行输入方面的一些限制, 这时候,就需要继承BaseConverter类,然后写自己的规则了。 这里只是举个简单的例子:

代码语言:javascript复制
from flask import Flask
from werkzeug.routing import BaseConverter

app = Flask(__name__)

class RegexConverter(BaseConverter):
    """自定义转化器类"""
    def __init__(self, url_map, regex):
        super(RegexConverter, self).__init__(url_map)
        self.regex = regex

    def to_python(self, value: str):
        return value

# 将自定义的转换器类添加到flask应用中
app.url_map.converters['re'] = RegexConverter

@app.route('/index/<re("1d{5}"):value>')   
def index(value):
    return "hello, world"

app.run()

# 只有如输入 127.0.0.1/index/123456 1开头,后面5位整数的才能匹配到

这个里面的匹配URL就可以使用正则的形式,匹配非常特殊的那种了。不过,一般用不到这么复杂的。

3.3 URL构建方法

在很多时候,在一个实用的视图中需要指向其他视图的连接,为了防止路径出现问题,我们可以让Flask框架帮我们计算链接URL。简单地给url_for()函数传入一个访问点,它返回将是一个可靠的URL地址

代码语言:javascript复制
@app.route('/')
def hello():
    return 'Hello world!'
    
@app.route('/test')
def test_url_for():
    print(url_for('hello'))  # 跳转到了hello函数下面执行

4. 请求、响应和会话

对于一个完整的HTTP请求,包括了来自客户端的请求对象(Request), 服务器端的响应对象(Respose)和会话对象(Session)等。 在Flask框架中,当然也具有这些对象, 这些对象不仅可以在请求函数中使用, 同时也可以在模板中使用。

4.1 请求对象Request

Flask包中, 可以直接引入request对象, 其中包含Form,args,Cookies,files等属性。

  • Form: 字典对象, 包含表单当中所有参数及值的键和值对
  • args: 解析字符串的内容, 是问号?之后的URL的一部分, 当使用get请求时, 通过URL传递参数时可以通过args属性获取
  • cookies: 用来保存cookie名称和值的字典对象
  • files: 属性和上传文件有关的数据

以一个登陆的例子看看如何搭配属性

代码语言:javascript复制
from flask import request, session, make_response

@app.route('/login', methods=['POST', 'GET'])
def logion():
	if request.method == 'POST':
		if request.form['username'] == 'admin':
			session['username'] = request.form['username']
			response = make_response('Admin login successfully!')
			response.set_cookie('login_time', time.strftime('%Y-%m-%d' %H:%M:%S'))
			return 'Admin login successfully!'
	elif request.method == 'GET':
		if request.args.get("username") == 'admin':
            session['username'] = request.form['username']
            return 'Admin login successfully!'
    else:
            return 'No such user!'

app.secret_key = '123456'

可以根据method属性判断当前请求的类型,通过form属性可以获取表单信息,并通过session来存储用户登陆信息。当然这里的session,可以换成字典,然后把信息存储到数据库里面去。

由于现在前后端交互会采用json的数据格式进行传输, 因此当前端请求的数据是json类型的时候, 可以使用get_data()方法来获取。

代码语言:javascript复制
from flask import Flask, jsonify, request
@app.route('/login', methods=["POST"])
def login():
    request_str = request.get_data()
    request_dict = json.loads(request_str)
    # 然后,就可以对request_dict进行处理了,相当于从后端拿到了前端的数据

4.2 响应对象response

如果函数试图想向前端返回数据, 必须是Response对象,主要有下面几种返回数据的格式:

试图函数return多个值

代码语言:javascript复制
@app.route("/user_one")
def user_one():
    return "userInfo.html", "200 Ok", { 
     "name": "zhangsan"; "age":"20"}

使用Response创建 可以通过直接创建Response对象,配置其参数。

代码语言:javascript复制
from flask import Response

@app.route("/user_one")
def user_one():
    response = Response("user_one")
    response.status_code = 200
    response.status = "200 ok"
    response.data = { 
     "name": "zhangsan"; "age":"20"}
    return response

由于现在前后端交互往往采用的是json的数据格式,因此可以将数据通过 jsonify 函数将其转化成json格式,再通过response对象发送给前端。

当然,这些东西直接这么写,可能会很抽象,后面一个小例子一串就了然, 这里可以先有个印象。

5. 重定向与错误处理

5.1 重定向

当一个请求过来后可能还需要请求另一个视图函数才能达到目的, 就可以调用redirect(location, code=302, Response=None)函数指定重定向页面。

代码语言:javascript复制
from flask import Flask, redirect, url_for

app = Flask(__name__)

@app.route("/demo")
def demo():
    url = url_for("demo2")  # 路由反转,根据视图函数名获取路由地址
    return redirect(url)   # 相当于到了/demo2这个页面,显式this is demo2 page

@app.route("/demo2")
def demo2():
    return "this is demo2 page"

@app.route("/")
def index():
    # 使用方法:redirect(location, code=302, Response=None) 
    return redirect("/demo", 301)

url_for函数我理解是能根据给定的url映射到对应的函数,比如给定demo2, 就映射到了demo2(), 但具体执行, 应该是redirect()函数起作用。

5.2 错误处理

当请求或服务器出现错误的时候, 我们希望遇到特定错误代码走不通的处理错误逻辑, 可以使用errorhandler()装饰器

代码语言:javascript复制
from flask import render_template   # 渲染页面

@app.errorhandler(404)
def page_not_found(error):
    return render_template('page_not_found.html'), 404

当遇到404错误时,会调用page_not_found()函数,返回元组数据,第一个元素是”page_not_found.html”的模板页,第二个元素代表错误代码,返回值会自动转成 response 对象。 如果这个地方想在网页里面放张图片的话,一定要放到static目录里面才行, 访问的是静态文件目录, 这个static名字不能改。

这个东西主要是为了后面处理异常,如果满足什么条件,就进行什么样的处理:

代码语言:javascript复制
from flask import abort
@app.route('/index', methods=['GET', 'POST'])
def index():
		if request.method == 'GET':
				return render_template('index.html')
		if request.method == 'POST':
				name = request.form.get('name')
				password = request.form.get('password')
				if name == 'zhangsan' and password == '123':
								return 'login success'
				else:
								abort(404)
								return None

6. 构建form表单,为交互做准备

上面整理了那么一大推, 这里想通过一个例子串一下, 否则总会有一股朦胧之感, 由于我不是很懂前端, 这里就简单参考代码写一个前端页面, 不用很复杂,就构建一个输入用户名和密码的对话框,然后点击提交,看看与后端的交互效果。

前端页面的代码如下:

这个布局方式也是蛮重要的, 就是先建立一个templates目录,这个目录可以认为是有一个模板目录,默认定义了一些前后端交互的代码格式。这个模板是jinjia2(右击目录,mark directory as设置), 然后在该目录下创建一个HTML界面。

然后在上一级目录,创建一个form表单文件,把这个HTML渲染出来:

代码语言:javascript复制
from flask import Flask, render_template

app = Flask(__name__)

@app.route('/index')
def index():
    return render_template('index.html')  # 渲染当前的html页面

if __name__ == '__main__':
		app.run()

# 输入127.0.0.1:5000/index 就会出来写的那个html页面了,然后输入密码,提交,就会得到一个get请求

此时,就能把前端的html页面显示出来。

当然,比较陋, 但演示足够。下面看看如何交互。

7. 前后端交互小例子

这里前端,从上面的两个框里输入用户名和密码,然后点击提交给后端。 后端接收过来, 把用户和密码封装起来, 给到另一个前端页面, 然后另一个前端页面就能用这个数据了。

首先, 需要先修改上面前端页面数据, 把提交请求的方式改为POST,非常简单, 只需要修改这里。

然后在总目录下建立了request对象.py文件,在这里面写接收数据的逻辑

代码语言:javascript复制
from flask import Flask, render_template
from flask import request

app = Flask(__name__)

@app.route('/index', methods=['GET', 'POST'])
def index():
    if request.method == 'GET':
        # 渲染index页面
        return render_template('index.html')
    elif request.method == 'POST':
        # 获取数据
        data = { 
   }
        data['name'] = request.args.get('name')   # 后面这个name和前端的name保持一致
        data['passwd'] = request.args.get('password')

        # 返回到前端去
        return render_template('index2.html', data=data)

    return render_template('index.html')

app.run()

其实也非常简单,输入网址的时候,显式的就是index.html页面,这个页面就是让用户输入用户名密码,然后提交即可,此时由于修改了index的提交方式是post请求,所以后端这块捕捉到,拿到传过来的数据, 给到index2.html, 此时index2.html就可以直接拿到data使用或者用来展示。

index2.html页面此时就能使用data数据了。

框里的这两个,就是index.html传给后端,然后后端传过来的数据, 可以直接在index2.html中显示。 当然,这里的{ {变量名}}的这种定义格式,就是模板事先定义好的,如果不是jinjia2模板,可能不能使用。所谓模板,就是事先定义了一些前后端交互的规则。

上面就是一个前后端交互的小例子啦, 其实flask框架用起来还是比较容易上手的。

8. 介绍两款工具

这里主要是介绍这两天用到的两个工具,SQLAlchemy和Postman。

8.1 SQLAlchemy

这是一个功能强大的python ORM工具包, 也就是提供了API去操作数据库里面的表的相关操作,而不是编写原始的SQL语句,非常方便。安装

代码语言:javascript复制
# 安装
pip install SQLalchemy
8.1.1 连接数据库

下面创建连接,也就是连接到我们的mysql数据库:

代码语言:javascript复制
from sqlalchemy import create_engine

def mysql_db(host='127.0.0.1', dbname='3306'):
	engine = create_engine("mysql pymysql://root:123456@{}:49168/{}?charset=utf8".formate(host, dbname))
	print(engine) # Engine(mysql pymysql://root:***@127.0.0.1:49168/3306?charset=utf8)

通过create_engine函数已经创建了Engine,在Engine内部实际上会创建一个Pool(连接池)和Dialect(方言),并且可以发现此时Engine并不会建立连接,只会等到执行到具体的语句时才会连接到数据库。上述代码默认本地已经存在并开启mysql服务。

代码语言:javascript复制
create_engine("mysql://user:password@hostname/dbname?charset=utf8",
                       echo=True,
                       pool_size=8,
                       pool_recycle=60*30)

第一个参数是和框架表明连接数据库所需的信息,“数据库 数据库连接框架://用户名:密码@IP地址:端口号/数据库名称?连接参数”;echo是设置当前ORM语句是否转化为SQL打印;pool_size是用来设置连接池大小,默认值为5;pool_recycle设置连接失效的时间,超过时间连接池会自动断开。

8.1.2 创建数据库表类

用于SQLAlchemy是对象关系映射,在操作数据库表时是通过操作对象实现的, 每一条记录其实是一个对象,所以需要先创建一个数据库表类说明字段信息。

代码语言:javascript复制
from sqlalchemy import create_engine, Column, Integer, String
from sqlalchemy.ext.declarative import declarative_base

Base = declarative_base()

class User(Base):
	__tablename__ = 'UserInfo'  # 表名
	# 数据库字段的类型
	index = Column(Integer(), primary_key=True)
	user_id = Column(Integer(), unique=True)
	username = Column(String(30))
	passwd = Column(String(500))

	def __init__(self, index, user_id, username, passwd):
		self.index = index
		self.user_id = user_id
		self.username = username
		self.paswd = passwd

这个可以当做是固定套路格式, 通过declarative_base()函数,可以将python类和数据库表进行关联映射,并通过 _tablename_ 属性将数据库模型类和表进行管理。其中Column() 表示数据表中的列,Integer()String()表示数据库的数据类型。

8.1.3 操作数据库

创建完连接, 需要借助sqlarchemy中的session来创建程序与数据库之间的会话,此时通过sessionmarker()函数创建。

代码语言:javascript复制
def mysql_db(host='127.0.0.1', dbname='test'):
	engine = create("mysql pymysql://root:123456@{}:49168/{}?charset=utf8mb4".format(host,dbname))
	
	session = sessionmaker(bind=engine)
	Base.metadata.create_all(engine)
	return engine, session()

这样,相当于正式与mysql建立了连接时候的会话。 session常用的方法:

  • flush: 预提交,提交到数据库文件,此时还未写入数据库文件中
  • commit: 提交了一个事务
  • rollback: 回滚
  • close: 关闭session连接

下面演示下数据库里面的增删改查。

增加数据

代码语言:javascript复制
# 增加一个用户
engine, session = mysql_db()

user = User("100", "zhangsan", "11111")
session.add(user)
session.commit()

# 也可以通过addall批量提交
engine, session = mysql_db()
user1 = User("101","lisi","11111")
user2 = User("102","wangwu","22222")
session.add_all([user1,user2])
session.commit()

不用我们事先建立数据库和表, 调用程序的时候,会自动建立好。 把用户的信息封装成一个对象,然后采用add的方式就可以添加进去了。 当然session.add()不会直接提交到数据库,当执行了commit()之后才会提交。 这时候,就不用什么insert table_name values …。

查询数据

代码语言:javascript复制
engine, session = mysql_db()
users = session.query(User).filter_by(passwd='11111').all()

for item in users:
    print(item.username,item.passwd)

通过上面代码就可以访问数据库, 类似于select操作了, 其中query()返回一个query对象,在这里指明查哪个大类(这里面映射一个数据表),告诉去哪个表里查。 当然此时并没有真正去查询, 只有等到具体执行函数count(), first(), all()等采取数据库查询。 当然,还可以使用filter()方法指定查询条件,类似where。 这里其实有两种写法:

修改数据

代码语言:javascript复制
session.query(User).filter_by(username="zhangsan").update({ 
     'passwd': "123456"})

删除数据

代码语言:javascript复制
session.query(User).filter(User.username == "zhangsan-test").delete()
session.commit()

8.2 Postman

当然这个东西由于也是刚接触,并不是太会用。 这个东西是有个接口测试工具, 是为了验证后端开发的接口是否可用。

因为真正开发大项目,前后端是分离开发的, 并且此时前端可能没有完全搭建好,所以接口测试的时候,postman,就相当于一个客户端, 可以模拟用户发起各类的HTTP请求, 将请求数据发送给服务端, 来获取对应的响应结果。 这样就能测试出后端的函数逻辑是否正确。

我这里是偶然接触到,因为学习上面新闻推荐系统的时候,我这边后端的每个py文件都运行通过了,此时想基于界面传数据看看效果,结果就是和前端的vue框架连不起来。 上面我自己写HTML文件好好的, 一旦用上vue框架,再去访问网址总是报错或者被拒绝啥的。

所以,这里就想看看到底是后端给的网址和接口不对,还是前端vue的问题,那么怎么测试呢? 意哥就告诉了我这个工具,用他来模拟前端,给后端发请求,看看后端能返回结果不。

当然具体的下载和使用, 我给出两篇参考文档postman教程, postman教程大全, 这玩意也是个软件,所以直接Windows下载安装即可。

打开之后, 我们新建一个collections,其实就是目录,然后在这里面新建一个request请求,就可以测试了。

我这里给出我这边的测试例子, 我当时想通过postman测试下,能不能访问到后端。测试的后端函数是这个:

代码语言:javascript复制
@app.route('/recsys/register', methods=["POST"])
def register():
    """用户注册 """
    request_str = request.get_data()
    request_dict = json.loads(request_str)
    print(request_dict)

    user = RegisterUser()
    user.username = request_dict["username"]
    user.passwd = request_dict["passwd"]

    # 查询当前用户名是否已经被用过了
    result = UserAction().user_is_exist(user, "register")

    if result != 0:
        return jsonify({ 
   "code": 500, "mgs": "this username is exists"})

    #user.userid = snowflake.client.get_guid() # 雪花算法
    user.userid = 20211971672
    user.age = request_dict["age"]
    user.gender = request_dict["gender"]
    user.city = request_dict["city"]
    print("hello world")

    # 添加注册用户
    save_res = UserAction().save_user(user)
    if not save_res:
        return jsonify({ 
   "code": 500, "mgs": "register fail."})

    return jsonify({ 
   "code": 200, "msg": "register success."})

用户注册函数, 这是一个post请求格式的,然后需要传入用户的相关参数,给到后端,后端把这个存到用户注册表里面去。然后返回成功信息。

其实逻辑很简单,首先, 建立post请求格式在postman的操作, 首先请求格式改成POST,然后headers这里需要设定json格式。

然后, 在body里面传入请求参数,也就是用户的注册信息, 这里是一个字典的形式

这样,点击右上角send即可发送了。根据下面后端返回的信息,说明后端这块是可以被访问的,没有什么问题。如果想发送get请求,以及传参数,还可以这样:

那,这就确定了, vue框架的配置有问题。

9. 新闻推荐系统vue和flask是怎么联系起来的呢?

这里主要是记录下解决上面这个问题的方法, 因为我这边遇到了vue服务开启完了之后, 输入网址并没有到相应的界面中去,而是报错。 这个问题还是困扰我一段时间的,一开始以为是后端那边的网址不能访问, 但用了postman之后,发现后端这边没问题。

于是我觉得是我vue那边配置有问题,因为我对vue内部一窍不通, 并且我伙伴们之前都测试好了,不可能是代码方面的问题。

于是乎,开始排查路径问题: 这篇文章启发

这个没有问题。下面这里也需要改:

这样操作完了,然后在浏览器输入

这样一顿操作之后,就搞定了上面的问题。202.199.6.190是我实验室服务器的地址。

当然我后端是这样:

总结起来, 就是需要修改前端的main.js里面的网址,然后修改package.json里面的主机地址。 然后访问的时候是从前端running的地址进行访问。

当然,开启前端的过程中还遇到一个奇葩的报错问题:

这个问题我也不知道是啥原因, vue涉及到盲区, 但下面这行代码却能无脑搞定,挺神奇:

代码语言:javascript复制
# 命令行输入
echo fs.inotify.max_user_watches=524288 | sudo tee -a /etc/sysctl.conf && sudo sysctl -p

到这里就差不多了,花了两三天的探索,终于把整个系统换了我实验室服务器跑出来,然后整理这篇文章记录下, 实测能运行, 感兴趣的伙伴可以玩玩啦

0 人点赞