当前位置:   article > 正文

Flask框架的学习---01_flask 绑定ip

flask 绑定ip

1.工程搭建:

(1) 安装flask: pip3 install flask

(2)命令行:

(1)终端运行:flask run 

(2)绑定IP地址和端口:Flask run -h 127.0.0.1 -p 8083 修改端口号

  • (3)启动项目: pyhthon app.py
    • ​​​​​​​  (4)  设置真实项目:FLASK_APP = "RealProject"
  • (5)生产环境:set FLASK_ENV=production
  • (6)开发模式:set FLASK_ENV=development 

注意:虽然 flask 命令可以方便地启动一个本地开发服务器,但是每次应用代码 修改之后都需要手动重启服务器。这样不是很方便, Flask 可以做得更好。如果你打开 调试模式,那么服务器会在修改应用代码之后自动重启,并且当应用出错时还会提供一个 有用的调试器。在命令行中,如果需要打开所有开发功能(包括调试模式),那么要在运行服务器之前导出 FLASK_ENV 环境变量并把其设置为 development:

2. flask框架的路由:

terminal中输入显示所有的路由:flask routes

(1)  路由定义

  1. from flask import Flask
  2. app = Flask(__name__)
  3. """
  4. 路由设置的注解路径: /index
  5. """
  6. @app.route('/index',methods=['POST','GET'])
  7. def hello_world():
  8. return 'Hello World!'
  9. """
  10. 路由的路径不能相同,每个函数对应不同的路由;不同的功能;
  11. """
  12. @app.route('/return')
  13. def return_content():
  14. return '你好!'
  15. """
  16. 启动本地服务:
  17. """
  18. if __name__ == '__main__':
  19. '设置ip 和端口号'
  20. app.run(debug=True,host='127.0.0.1',port=8083)

 

(2)路由中传递参数:

除了默认字符串变量部分之外,还可以使用以下转换器构建规则:

转换器描述
string(缺省值) 接受任何不包含斜杠的文本
int接受正整数
float接受正浮点数
path类似 string ,但可以包含斜杠
uuid接受 UUID 字符串
  1. #在路由中传递参数
  2. @app.route('/get_name/<name>',methods=['POST','GET'])
  3. def get_params(name):
  4. return '你好!' + name

(3)request 对象的使用:

1)HTTP请求方法:

GET以未加密的形式将数据发送到服务器,最常见的方法。
HEAD和GET方法相同,但没有响应体。
POST用于将HTML表单数据发送到服务器,POST方法接收的数据不由服务器缓存。
PUT用上传的内容替换目标资源的所有当前表示。
DELETE删除由URL给出的目标资源的所有当前表示。

2)参数格式:

data(请求的数据,类型为string)

form(表单的数据)、

args(记录请求中的查询参数?号后面的参数)

headers

method(get\post)

cookies

url

files:文件类型;上传图片)

(4)响应对象:response:

1)返回模板:render_template() :返回一个模板文件

2)重定向redirect:  跳转到其他的路由

3)返回json数据: ( json.load() :读json 文件)

 json.dumps() :写json文件;

 jsonify() :返回为json,同时设置响应头;

4)Cookie使用: 存储在客户端,显示用户的访问记录

一般使用response对象.set_cookie() 来设置cookie

 得到cookie: request.Cookies.get("XXX") 得到cookie

5)Session使用:保存前端提交的状态的数据;存放在浏览器服务器上;

1)设置session:

2.得到session:session.get() :

3删除session:

①删除单条session值,可以采用session.pop('name')方法;
②清空整个session内容,则采用session.clear()方法;

6)abort函数的使用:异常处理函数;

  • 使用类似于python中的raise函数,可以在需要退出请求的地方抛出错误,并结束该请求;
  • 我们可以使用app.erroehandler装饰器来进行异常的捕获与自定义:
  1. from flask import Flask,render_template,request,abort
  2. app = Flask(__name__)
  3. @app.route("/",methods=['GET','POST'])
  4. def index():
  5. if request.method == 'GET':
  6. return render_template('index.html')
  7. elif request.method == 'POST':
  8. name = request.form.get('name')
  9. password = request.form.get('password')
  10. if name == 'zhangsan' and password == '123456':
  11. return 'login sucess'
  12. else:
  13. # abort的用法类似于python中的raise,在网页中主动抛出错误
  14. abort(404)
  15. return None
  16. # 自定义错误处理方法,将404这个error与Python函数绑定
  17. # 当需要抛出404error时,将会访问下面的代码
  18. @app.errorhandler(404)
  19. def handle_404_error(err):
  20. # return "发生了错误,错误情况是:%s"%err
  21. # 自定义一个界面
  22. return render_template('404.html')
  23. if __name__ == '__main__':
  24. app.run()

7)url_for实现反转:

url_for是实现url反转的工具,即视图函数→url;
静态文件引入:url_for('static', filename='文件路径')

(5)请求钩子:

中间件(中间件对所有的view都起作用:):是一个类,然后定义pre-process、after-process方法;

请求处理的过程:pro-process----view -----after-process------>(return response)

请求钩子的类别:

  1. before_request:在每一次请求之前调用;
  2. before_first_request:与before_request的区别是,只在第一次请求之前调用;只调用一次
  3. after_request每一次请求之后都会调用;
  4. teardown_request每一次请求之后都会调用;

请求钩子执行顺序:

before-first-request-----before-request----after-request-------teardown-request(接近结尾处理)

3. flask框架的视图:

(1) add_url_rule的初登场

欲实现url与视图函数的绑定,除了使用路由装饰器@app.route,我们还可以通过add_url_rule(rule,endpoint=None,view_func=None)方法

rule:设置的url

endpoint:给url设置的名称

view_func:指定视图函数的名称

(2) 视图函数和类视图:

类视图的引入

之前我们所定义的视图都是通过函数来实现的,所以称之为视图函数,但其实视图还可以由类来实现,即类视图

标准类视图:

定义时需要继承flask的views.View这一基类;
每个类视图内必须包含一个dispatch_request方法,每当类视图接收到请求时都会执行该方法,返回值的设定和视图函数相同;
区别:

视图函数可以通过@app.route和app.add_url_rule来进行注册(映射到url),但类视图只能通过app.add_url_rule来注册,注册时view_func不能直接使用类名,需要调用基类中的as_view方法来为自己取一个“视图函数名”

  1. from flask import Flask,render_template,views
  2. app = Flask(__name__)
  3. # 定义父视图类继承基类View
  4. class Ads(views.View):
  5. def __init__(self):
  6. super(Ads, self).__init__()
  7. # 实例属性
  8. self.context={
  9. 'ads':'这是对联广告!'
  10. }
  11. # 定义子视图类继承父类并实现工程
  12. class Index(Ads):
  13. def dispatch_request(self):
  14. # 字典传参方式==不定长的关键字传参
  15. return render_template('class_mould/index.html',**self.context)
  16. class Login(Ads):
  17. def dispatch_request(self):
  18. # 字典传参方式==不定长的关键字传参
  19. return render_template('class_mould/login.html',**self.context)
  20. class Register(Ads):
  21. def dispatch_request(self):
  22. # 字典传参方式==不定长的关键字传参
  23. return render_template('class_mould/register.html',**self.context)
  24. # 注册我们创建的类视图,as_view给类视图起名
  25. app.add_url_rule(rule='/',endpoint='index',view_func=Index.as_view('index'))
  26. app.add_url_rule(rule='/login/',endpoint='login',view_func=Login.as_view('login'))
  27. app.add_url_rule(rule='/register/',endpoint='register',view_func=Register.as_view('register'))
  28. if __name__=='__main__':
  29. print(app.view_functions)
  30. app.run(debug=True)

(3) 蓝图的使用:
一个蓝图就是一个模块;视为一种容器对象;有自己的模板文件、静态文件等;

蓝图使用方式:创建蓝图和注册蓝图。

 蓝图内部的静态文件: static_folder:静态文件夹

 4. jinja2模板引擎:

(1) 模板的使用:

  • 后端传数据:Flask通过render_template来实现模板的渲染,要使用这个方法,我们需要导入from flask import rander_template,模板中注释需放在{# #}中
  • 模板的第一个参数为指定的模板文件名称,如自定义的html文件,第二个或者更多参数为可选项,用于向模板中传递变量。
  • 如果有多个变量需要传递,我们可以不需要一个一个进行传参,直接使用**locals()替代我们在当前视图函数中定义的所有变量:
  1. from flask import Flask,render_template
  2. app = Flask(__name__)
  3. # 给前端模板传参
  4. @app.route("/")
  5. def index():
  6. data = {
  7. 'name':'张三',
  8. 'age':18,
  9. 'mylist':[1,2,3,4,5,6,7]
  10. }
  11. # 以键值对的形式传参给模板index2.html
  12. # 左边是形参:data);
  13. # 右边是我们给这个变量传的值(实参:字典data);
  14. return render_template('index2.html',data=data)
  15. if __name__ == '__main__':
  16. app.run()

前端接受数据:

前端html模板内需要在双括号{{ }}中使用该变量:
如果想给该变量添加属性便于CSS修改格式,我们可以在变量后添加括号,并在括号内定义class、id等属性

  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <title>Title</title>
  6. </head>
  7. <body>
  8. hello world
  9. <br>
  10. <!-- 对传入变量的使用并显示:在双括号内,和python中用法类似 -->
  11. {{ data }}
  12. <br>
  13. {{ data['name'] }}
  14. <br>
  15. {{ data.name }}
  16. <br>
  17. mylist:{{ data.mylist }}
  18. <br>
  19. mylist[1]:{{ data.mylist[1] }}
  20. <br>
  21. count:{{ data.mylist[1]+data.mylist[2] }}
  22. </body>
  23. </html>

(2)模板中的控制语句:

  • jinja2模板引擎中也可使用if和for控制语句,但是语句需要放置在{% %}中;

  • if条件判断语句必须包含结束标签{% endif %},其他部分与python中类似,可以与比较运算符> >= < <= == !=结合使用,或与逻辑运算符and,or,not,()结合使用;

  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <title>Title</title>
  6. </head>
  7. <body>
  8. {% if name==1 %}
  9. <h1>恭喜你抽中了一等奖!</h1>
  10. {% if name==2 %}
  11. <h1>恭喜你抽中了二等奖!</h1>
  12. {% else %}
  13. <h1>恭喜你抽中了三等奖!</h1>
  14. {% endif %}
  15. </body>
  16. </html>
  • for循环控制语句在模板内的用法也和python中类似,遍历的对象可以是字典、元组、列表等,但需要注意的是在模板中无法使用continue和break来对循环进行控制;
  1. {% for 目标 in 对象 %}
  2. <p>目标</p>
  3. {% endfor %}

(3)过滤器的使用与自定义:

  • 可以在前端模板内{{ 内容 | 过滤器 }}的" | "后使用;
  • 可以使用add_template_filter(函数方法名,'过滤器名')来自定义过滤器;
  1. # 自定义过滤器
  2. def list_step(li):
  3. # 返回列表,步长为2
  4. return li[::2]
  5. # 注册模板过滤器(filter)
  6. # 参数1为该过滤器调用的函数,参数2为在前端中调用该过滤器使用的名称
  7. app.add_template_filter(list_step,'li2')
  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <title>Title</title>
  6. </head>
  7. <body>
  8. <!-- 过滤器的使用 -->
  9. <!-- 全大写 -->
  10. {{ 'hello_world' | upper }}
  11. <br>
  12. <!-- 单词首字母大写 -->
  13. {{ 'hello world' | title }}
  14. <br>
  15. <!-- 替换左边的内容为右边的内容 -->
  16. {{ 'hello_world' | replace('hello','hi') }}
  17. <br>
  18. <!-- 调用自定义的过滤器 -->
  19. mylist列表:{{ data.mylist | li2 }}
  20. </body>
  21. </html>

(4) include的使用:

  • include用于在一个模板的指定位置导入另一个模板的内容,区别于宏的调用,include更像从另一个模板“复制+粘贴”;
  • include同样在{% %}中使用,采用语句{% include 模块名 %},相当于复制。

(5) 加载静态文件

静态文件一般是我们在开发过程中用到的图片文件、css文件和js文件,在Flask工程中通常包含一个static文件目录,当需要调用静态文件是将会默认在该目录下进行查询,固不需要使用相对路径;
通常我们会在static文件目录下定义名为css、image和js的文件夹分别存储这些静态文件;
加载静态文件通常配合url_for函数使用(需要在双括号内调用),将模板标签的src、herf属性通过url_for(静态文件名称)设置为反转url要比使用相对路径更好

  1. <head>
  2. <!-- 导入js文件 -->
  3. <script type="text/javascript" src="{{url_for('static',filename='js/jquery-3.5.1/jquery-3.5.1.js')}}"></script>
  4. <!-- 导入css文件 -->
  5. <link rel="stylesheet" href="{{url_for('static',filename='css/car.css')}}">
  6. </head>
  7. <body>
  8. <!-- 导入图片 -->
  9. <img alt="" src="{{ url_for('static',filename='image/car.jpg') }}"/>
  10. </body>

(6)extends继承模板

  • 在include中,我们对于当前模板需要插入的代码块,可以在其他模板中定义,然后用include导入进来,外部模块是当前模块的补充,引入新的子模块
  • 而在extends中,我们当前的模板则是待装载的代码块,需要我们继承一个框架来搭载这些代码块,这时候就需要extend来导入框架(基类)模块了;在继承父类的模板基础上,然后生成自己的模板。
  • 通常使用{% block xxx %} xxxx {% endblock %}来充当占位符。

5. flask数据交互:

(1) 使用flask传统的处理表单:

1)传统的前端通用表单,需要前后端共同完成操作,前端需要使用form标签来定义表单,而后端则需要使用request.form来获取post请求中的表单数据:

  1. # 判断请求方式
  2. if request.method == 'POST':
  3. # 获取表单中name为username的文本域提交的数据
  4. name = request.form.get('username')
  5. # 获取表单中name为password的文本域提交的数据
  6. password = request.form.get('password')
  7. return name+" "+password

2)使用第三方组件:flask-wtf 和wtforms 来实现后端独立完成的表单操作;

  • wtforms安装:pip install wtforms
  • flask-wtf安装:pip install Flask-WTFpip install flask-wtf

wtforms依照功能类别来说wtforms分别由以下几个类别:

  1. Forms: 主要用于表单验证、字段定义、HTML生成,并把各种验证流程聚集在一起进行验证。
  2. Fields: 包含各种类型的字段,主要负责渲染(生成HTML文本域)和数据转换。
  3. Validator:主要用于验证用户输入的数据的合法性。比如Length验证器可以用于验证输入数据的长度。
  4. Widgets:html插件,允许使用者在字段中通过该字典自定义html小部件。
  5. Meta:用于使用者自定义wtforms功能(配置),例如csrf功能开启。
  6. Extensions:丰富的扩展库,可以与其他框架结合使用,例如django。

(2) flash 闪现的使用:

  • 导入:from flask import flash
  • 后端的使用:flash("message"),message为消息内容;
  • 前端通过遍历get_flashed_messages()获取flash消息内容;

(3) Flask实现文件上传(后面补充)

  • 对于单文件的上传,主要用到flask_wtf.file库下的上传字段类:FileField,以及检验组件:FileRequired和 FileAllowed

6. flask访问数据库:

(1) Flask-SQLAlchemy数据库:

安装 :

pip3 install Flask-SQLAlchemy

SQLAlchemy是一个基于Python实现的ORM (Object Relational Mapping,对象关系映射)框架。该框架建立在DB API (数据库应用程序接口系统) 之上,使用关系对象映射进行数据库操作。简言之便是将类和对象转换成SQL,然后使用数据API (接口) 执行SQL 并获取执行结果。
它的核心思想于在于将关系数据库表中的记录映射成为对象,以对象的形式展现,程序员可以把对数据库的操作转化为对对象的操作。

1)Flask-SQLALchemy的ORM框架便可以实现将操作数据库转变为操作对象,一个book表被抽象成了一个Book类,一个表中的id、tiltle、publishing_office、isbn、storage_time字段被抽象成一个类的五个属性,而该表的一条数据记录就抽象成该类的一个实例化对象,不用再写烦琐的底层SQL语句了。

(2) 初始化数据库配置:

  1. USERNAME = 'root' #设置登录账号
  2. PASSWORD = '123456' #设置登录密码
  3. HOST = '127.0.0.1' #设置主机地址
  4. PORT = '3306' #设置端口号
  5. DATABASE ='flaskdb' #设置访问的数据库
  6. # 创建URI(统一资源标志符)
  7. '''
  8. SQLALCHEMY_DATABASE_URI的固定格式为:
  9. '{数据库管理系统名}://{登录名}:{密码}@{IP地址}:{端口号}/{数据库名}?charset={编码格式}'
  10. '''
  11. DB_URI = 'mysql://{}:{}@{}:{}/{}?charset=utf8'.format(USERNAME,PASSWORD,HOST,PORT,DATABASE)
  12. # 设置数据库的连接URI
  13. SQLALCHEMY_DATABASE_URI = DB_URI
  14. # 设置动态追踪修改,如未设置只会提示警告
  15. SQLALCHEMY_TRACK_MODIFICATIONS = False
  16. # 设置查询时会显示原始SQL语句
  17. SQLALCHEMY_ECHO = True
  • 上述配置文件设置完后,在flask程序文件下导入该文件,再用app.config.from_object方法导入到flask对象内即可;

(3) 表模型的定义与数据库映射

SQLAlchemy允许我们依据数据库的表结构来构建数据模型,即用python类的方式定义一个表模型,再通过调用create_all()方法,就可以将我们定义的所有表模型全部映射为数据库下的表;
但要注意的是每次运行create_all()这行代码时都会将所有表创建一次,导致重复创建表的问题,可以在前面添加一行drop_all()代码来删除已经创建的表;
创建表名:在用类的方式定义表模型时,使用__tablename__='<表名>'来将字符串对象设为表名,

创建列名:使用<列名>=db.Column()来将Column类的实例对象设为表的字段;我们为字段(列)指定的数据类型和约束条件,作为Column实例化时的参数;

SQLAlchemy创建表了,并可以尝试着进行插入记录的操作SQLAlchemy.session.add()

  1. from flask import Flask
  2. from flask_sqlalchemy import SQLAlchemy
  3. import flask学习.config
  4. from datetime import * # datatime库下的datatime类重名了
  5. app = Flask(__name__)
  6. app.config.from_object(flask学习.config)
  7. # 初始化一个SQLAlchemy对象(该步要在导入config后执行)
  8. # 实例化的同时将与数据库相关的配置读入
  9. db = SQLAlchemy(app)
  10. # 初始化app对象中与数据库相关的配置的设置,防止数据库信息泄露
  11. db.init_app(app)
  12. # 创建表模型类对象
  13. class Book(db.Model):
  14. __tablename__='book'
  15. id = db.Column(db.Integer, primary_key = True,autoincrement = True) #定义id字段
  16. title = db.Column(db.String(50),nullable = False) #定义title字段
  17. publishing_office = db.Column(db.String(100),nullable = False) #定义出版社字段
  18. isbn = db.Column(db.String(100),nullable = False) #定义isbn号字段
  19. storage_time = db.Column(db.DateTime, default = datetime.now) # 入库时间字段
  20. if __name__ == '__main__':
  21. # 删除数据库下的所有上述定义的表,防止重复创建
  22. db.drop_all()
  23. # 将上述定义的所有表对象映射为数据库下的表单(创建表)
  24. db.create_all()
  25. # 向表中插入记录:实例化-插入-提交
  26. book1 = Book(id='001',title='人工智能导论',publishing_office ='高等教育出版社',isbn='9787040479843')
  27. db.session.add(book1)
  28. db.session.commit()

(4)数据的增、删、改、查操作

  1. from flask import Flask
  2. from flask_sqlalchemy import SQLAlchemy
  3. import flask学习.config
  4. from datetime import * # datatime库下的datatime类重名了
  5. app = Flask(__name__)
  6. app.config.from_object(flask学习.config)
  7. # 初始化一个SQLAlchemy对象(该步要在导入config后执行)
  8. # 实例化的同时将与数据库相关的配置读入
  9. db = SQLAlchemy(app)
  10. # 初始化app对象中与数据库相关的配置的设置,防止数据库连接泄露
  11. db.init_app(app)
  12. # 创建表模型类对象
  13. class Book(db.Model):
  14. __tablename__='book'
  15. id = db.Column(db.Integer, primary_key = True,autoincrement = True) # 定义id字段
  16. title = db.Column(db.String(50),nullable = False) # 定义title字段
  17. publishing_office = db.Column(db.String(100),nullable = False) # 定义出版社字段
  18. price = db.Column(db.String(30), nullable=False) # 定义price号字段
  19. isbn = db.Column(db.String(50),nullable = False) # 定义isbn号字段
  20. storage_time = db.Column(db.DateTime, default = datetime.now) # 入库时间字段
  21. # 删除数据库下的所有上述定义的表,防止重复创建
  22. db.drop_all()
  23. # 将上述定义的所有表对象映射为数据库下的表单(创建表)
  24. db.create_all()
  25. # 添加数据的路由
  26. @app.route('/add')
  27. def add_record():
  28. book1 = Book(title='Python基础教程(第3版)', publishing_office ='人民邮电出版社', price = '68.30 ', isbn = '9787115474889')
  29. book2= Book(title='Python游戏编程快速上手第4版',publishing_office = '人民邮电出版社', price = '54.50', isbn = '9787115466419')
  30. book3 = Book(title='JSP+Servlet+Tomcat应用开发从零开始学',publishing_office = '清华大学出版社', price = '68.30', isbn = '9787302384496')
  31. db.session.add(book1)
  32. db.session.add(book2)
  33. db.session.add(book3)
  34. # 需要提交事务给数据库
  35. db.session.commit()
  36. return 'add success!'
  37. # 查找数据的路由
  38. @app.route('/query')
  39. def query_record():
  40. # 查找id=1的第一个对象
  41. result = Book.query.filter(Book.id == '1').first()
  42. print(result.title)
  43. # 查找publishing_office=人民邮电出版社的全体对象
  44. result_list = Book.query.filter(Book.publishing_office == '人民邮电出版社').all()
  45. for books in result_list:
  46. print(books.title)
  47. return 'query success!'
  48. # 修改数据的路由
  49. @app.route('/edit')
  50. def edit_record():
  51. # 查找id=1的第一个对象
  52. book1 = Book.query.filter(Book.id == '1').first()
  53. book1.price = 168
  54. # 需要提交事务给数据库
  55. db.session.commit()
  56. return 'edit success!'
  57. # 删除数据的路由
  58. @app.route('/delete')
  59. def delete_record():
  60. # 查找id=9的第一个对象
  61. book2 = Book.query.filter(Book.id == '9').first()
  62. db.session.delete(book2)
  63. # 需要提交事务给数据库
  64. db.session.commit()
  65. return 'delete success!'
  66. if __name__ == '__main__':
  67. app.run(debug=True)

1)数据的添加

  • 确保数据库已经建立好后,直接使用db.session.add(<实例化对象>)的方法就可以把依据某一个表类实例化的数据对象插入到对应表中;
  • 这一步操作需要进行事务提交db.session.commit()

2)数据的查找

数据的查找需要通过query.filter(<限制条件>)方法来实现,query继承自db.Model,query.filter返回的是查找到的所有满足限制条件的数据对象组成的列表,当没有限制条件时则返回表中所有记录对应的数据对象组成的列表;
可以使用first()来获取查找到的第一个数据对象,也可以用all()来获取查找到的全部数据对象(一个列表);

3)数据的修改

  • 数据的修改操作是基于数据的查找操作实现的,先通过查找记录获取到对应的数据对象,再对该对象的某一个字段进行修改即可;
  • 这一步操作需要进行事务提交db.session.commit()

4)数据删除:

  • 数据的删除和数据的修改一样,也是基于数据的查找实现的,先通过查找记录获取到对应的数据对象,再调用db.session.delete(<数据对象>)方法即可删除该数据对象与表中的记录;
  • 这一步操作需要进行事务提交db.session.commit()

(5)表模型的关联关系构建

数据库实体型(表)间有3种关联关系:一对一一对多多对多

在SQLAlchemy中,为了在表模型间创建上述的三种关联关系,

同样要在一个表模型中通过db.ForeignKey('表模型类.属性')的方式添加外键,绑定另一个表模型的主属性(primary_key);添加外键后,

还需要使用<字段名1> = db.relationship('<多方表名>',backref=db.backref('<字段名2>')[,secondary=<Table对象名>,uselist=False])的方法来正式构建关系。
 

(6) init_app作用:初始化数据库,但必须要提前传入flask对象。

只要在实例化SQLAlchemy对象的过程中,如果参数app不为空(判断是否传入了flask对象,参数app默认值为None),那么就会调用init_app方法来初始化flask对象中数据库部分的相关配置。这时如果我们提前为flask对象导入了配置文件,init_app就无法覆写我们自定义的配置内容,也就相当于“没有起作用”。


 

参考链接:Flask框架学习整理——从零开始入门Flask_时生丶的博客-CSDN博客

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/不正经/article/detail/604650
推荐阅读
相关标签
  

闽ICP备14008679号