赞
踩
(1)终端运行:flask run
(2)绑定IP地址和端口:Flask run -h 127.0.0.1 -p 8083 修改端口号
注意:虽然 flask 命令可以方便地启动一个本地开发服务器,但是每次应用代码 修改之后都需要手动重启服务器。这样不是很方便, Flask 可以做得更好。如果你打开 调试模式,那么服务器会在修改应用代码之后自动重启,并且当应用出错时还会提供一个 有用的调试器。在命令行中,如果需要打开所有开发功能(包括调试模式),那么要在运行服务器之前导出 FLASK_ENV 环境变量并把其设置为 development:
terminal中输入显示所有的路由:flask routes
- from flask import Flask
-
- app = Flask(__name__)
-
- """
- 路由设置的注解路径: /index
- """
- @app.route('/index',methods=['POST','GET'])
- def hello_world():
-
- return 'Hello World!'
-
- """
- 路由的路径不能相同,每个函数对应不同的路由;不同的功能;
- """
- @app.route('/return')
- def return_content():
- return '你好!'
- """
- 启动本地服务:
- """
- if __name__ == '__main__':
- '设置ip 和端口号'
- app.run(debug=True,host='127.0.0.1',port=8083)
除了默认字符串变量部分之外,还可以使用以下转换器构建规则:
转换器 | 描述 |
---|---|
string | (缺省值) 接受任何不包含斜杠的文本 |
int | 接受正整数 |
float | 接受正浮点数 |
path | 类似 string ,但可以包含斜杠 |
uuid | 接受 UUID 字符串 |
- #在路由中传递参数
- @app.route('/get_name/<name>',methods=['POST','GET'])
- def get_params(name):
- return '你好!' + name
GET | 以未加密的形式将数据发送到服务器,最常见的方法。 |
HEAD | 和GET方法相同,但没有响应体。 |
POST | 用于将HTML表单数据发送到服务器,POST方法接收的数据不由服务器缓存。 |
PUT | 用上传的内容替换目标资源的所有当前表示。 |
DELETE | 删除由URL给出的目标资源的所有当前表示。 |
data(请求的数据,类型为string)、
form(表单的数据)、
args(记录请求中的查询参数?号后面的参数)
headers
method(get\post)
cookies
url
files:文件类型;上传图片)
json.dumps() :写json文件;
jsonify() :返回为json,同时设置响应头;
一般使用response对象.set_cookie() 来设置cookie
得到cookie: request.Cookies.get("XXX") 得到cookie
1)设置session:
2.得到session:session.get() :
3删除session:
①删除单条session值,可以采用session.pop('name')
方法;
②清空整个session内容,则采用session.clear()
方法;
- from flask import Flask,render_template,request,abort
-
- app = Flask(__name__)
-
- @app.route("/",methods=['GET','POST'])
- def index():
- if request.method == 'GET':
- return render_template('index.html')
- elif request.method == 'POST':
- name = request.form.get('name')
- password = request.form.get('password')
- if name == 'zhangsan' and password == '123456':
- return 'login sucess'
- else:
- # abort的用法类似于python中的raise,在网页中主动抛出错误
- abort(404)
- return None
-
-
-
- # 自定义错误处理方法,将404这个error与Python函数绑定
- # 当需要抛出404error时,将会访问下面的代码
- @app.errorhandler(404)
- def handle_404_error(err):
- # return "发生了错误,错误情况是:%s"%err
- # 自定义一个界面
- return render_template('404.html')
-
- if __name__ == '__main__':
- app.run()
url_for是实现url反转的工具,即视图函数→url;
静态文件引入:url_for('static', filename='文件路径')
中间件(中间件对所有的view都起作用:):是一个类,然后定义pre-process、after-process方法;
请求处理的过程:pro-process----view -----after-process------>(return response)
请求钩子的类别:
before_request
:在每一次请求之前调用;before_first_request
:与before_request的区别是,只在第一次请求之前调用;只调用一次after_request
:每一次请求之后都会调用;teardown_request
:每一次请求之后都会调用;请求钩子执行顺序:
before-first-request-----before-request----after-request-------teardown-request(接近结尾处理)
欲实现url与视图函数的绑定,除了使用路由装饰器@app.route,我们还可以通过add_url_rule(rule,endpoint=None,view_func=None)
方法
rule:设置的url
endpoint:给url设置的名称
view_func:指定视图函数的名称
类视图的引入
之前我们所定义的视图都是通过函数来实现的,所以称之为视图函数,但其实视图还可以由类来实现,即类视图;
标准类视图:
定义时需要继承flask的views.View这一基类;
每个类视图内必须包含一个dispatch_request方法,每当类视图接收到请求时都会执行该方法,返回值的设定和视图函数相同;
区别:
视图函数可以通过@app.route和app.add_url_rule来进行注册(映射到url),但类视图只能通过app.add_url_rule来注册,注册时view_func不能直接使用类名,需要调用基类中的as_view方法来为自己取一个“视图函数名”
- from flask import Flask,render_template,views
-
- app = Flask(__name__)
-
- # 定义父视图类继承基类View
- class Ads(views.View):
- def __init__(self):
- super(Ads, self).__init__()
- # 实例属性
- self.context={
- 'ads':'这是对联广告!'
- }
-
- # 定义子视图类继承父类并实现工程
- class Index(Ads):
- def dispatch_request(self):
- # 字典传参方式==不定长的关键字传参
- return render_template('class_mould/index.html',**self.context)
- class Login(Ads):
- def dispatch_request(self):
- # 字典传参方式==不定长的关键字传参
- return render_template('class_mould/login.html',**self.context)
- class Register(Ads):
- def dispatch_request(self):
- # 字典传参方式==不定长的关键字传参
- return render_template('class_mould/register.html',**self.context)
-
- # 注册我们创建的类视图,as_view给类视图起名
- app.add_url_rule(rule='/',endpoint='index',view_func=Index.as_view('index'))
- app.add_url_rule(rule='/login/',endpoint='login',view_func=Login.as_view('login'))
- app.add_url_rule(rule='/register/',endpoint='register',view_func=Register.as_view('register'))
-
- if __name__=='__main__':
- print(app.view_functions)
- app.run(debug=True)
蓝图使用方式:创建蓝图和注册蓝图。
蓝图内部的静态文件: static_folder:静态文件夹
**locals()
替代我们在当前视图函数中定义的所有变量:- from flask import Flask,render_template
-
- app = Flask(__name__)
-
- # 给前端模板传参
- @app.route("/")
- def index():
- data = {
- 'name':'张三',
- 'age':18,
- 'mylist':[1,2,3,4,5,6,7]
- }
- # 以键值对的形式传参给模板index2.html
- # 左边是形参:data);
- # 右边是我们给这个变量传的值(实参:字典data);
- return render_template('index2.html',data=data)
-
- if __name__ == '__main__':
- app.run()
前端接受数据:
前端html模板内需要在双括号{{ }}中使用该变量:
如果想给该变量添加属性便于CSS修改格式,我们可以在变量后添加括号,并在括号内定义class、id等属性
- <!DOCTYPE html>
- <html lang="en">
- <head>
- <meta charset="UTF-8">
- <title>Title</title>
- </head>
- <body>
- hello world
- <br>
- <!-- 对传入变量的使用并显示:在双括号内,和python中用法类似 -->
- {{ data }}
- <br>
- {{ data['name'] }}
- <br>
- {{ data.name }}
- <br>
- mylist:{{ data.mylist }}
- <br>
- mylist[1]:{{ data.mylist[1] }}
- <br>
- count:{{ data.mylist[1]+data.mylist[2] }}
- </body>
- </html>
jinja2模板引擎中也可使用if和for控制语句,但是语句需要放置在{% %}
中;
if条件判断语句必须包含结束标签{% endif %},其他部分与python中类似,可以与比较运算符> >= < <= == !=
结合使用,或与逻辑运算符and,or,not,()
结合使用;
- <!DOCTYPE html>
- <html lang="en">
- <head>
- <meta charset="UTF-8">
- <title>Title</title>
- </head>
- <body>
- {% if name==1 %}
- <h1>恭喜你抽中了一等奖!</h1>
- {% if name==2 %}
- <h1>恭喜你抽中了二等奖!</h1>
- {% else %}
- <h1>恭喜你抽中了三等奖!</h1>
- {% endif %}
- </body>
- </html>
- {% for 目标 in 对象 %}
- <p>目标</p>
- {% endfor %}
{{ 内容 | 过滤器 }}
的" | "后使用;add_template_filter(函数方法名,'过滤器名')
来自定义过滤器;- # 自定义过滤器
- def list_step(li):
- # 返回列表,步长为2
- return li[::2]
-
- # 注册模板过滤器(filter)
- # 参数1为该过滤器调用的函数,参数2为在前端中调用该过滤器使用的名称
- app.add_template_filter(list_step,'li2')
- <!DOCTYPE html>
- <html lang="en">
- <head>
- <meta charset="UTF-8">
- <title>Title</title>
- </head>
- <body>
- <!-- 过滤器的使用 -->
- <!-- 全大写 -->
- {{ 'hello_world' | upper }}
- <br>
- <!-- 单词首字母大写 -->
- {{ 'hello world' | title }}
- <br>
- <!-- 替换左边的内容为右边的内容 -->
- {{ 'hello_world' | replace('hello','hi') }}
- <br>
- <!-- 调用自定义的过滤器 -->
- mylist列表:{{ data.mylist | li2 }}
- </body>
- </html>
{% %}
中使用,采用语句{% include 模块名 %}
,相当于复制。静态文件一般是我们在开发过程中用到的图片文件、css文件和js文件,在Flask工程中通常包含一个static文件目录,当需要调用静态文件是将会默认在该目录下进行查询,固不需要使用相对路径;
通常我们会在static文件目录下定义名为css、image和js的文件夹分别存储这些静态文件;
加载静态文件通常配合url_for函数使用(需要在双括号内调用),将模板标签的src、herf属性通过url_for(静态文件名称)设置为反转url要比使用相对路径更好。
- <head>
- <!-- 导入js文件 -->
- <script type="text/javascript" src="{{url_for('static',filename='js/jquery-3.5.1/jquery-3.5.1.js')}}"></script>
- <!-- 导入css文件 -->
- <link rel="stylesheet" href="{{url_for('static',filename='css/car.css')}}">
- </head>
- <body>
- <!-- 导入图片 -->
- <img alt="" src="{{ url_for('static',filename='image/car.jpg') }}"/>
- </body>
1)传统的前端通用表单,需要前后端共同完成操作,前端需要使用form标签来定义表单,而后端则需要使用request.form
来获取post请求中的表单数据:
- # 判断请求方式
- if request.method == 'POST':
- # 获取表单中name为username的文本域提交的数据
- name = request.form.get('username')
- # 获取表单中name为password的文本域提交的数据
- password = request.form.get('password')
- return name+" "+password
2)使用第三方组件:flask-wtf 和wtforms 来实现后端独立完成的表单操作;
pip install wtforms
pip install Flask-WTF
或pip install flask-wtf
wtforms依照功能类别来说wtforms分别由以下几个类别:
from flask import flash
;flash("message")
,message为消息内容;get_flashed_messages()
获取flash消息内容;flask_wtf.file
库下的上传字段类:FileField,以及检验组件:FileRequired和 FileAllowed;安装 :
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语句了。
- USERNAME = 'root' #设置登录账号
- PASSWORD = '123456' #设置登录密码
- HOST = '127.0.0.1' #设置主机地址
- PORT = '3306' #设置端口号
- DATABASE ='flaskdb' #设置访问的数据库
-
- # 创建URI(统一资源标志符)
- '''
- SQLALCHEMY_DATABASE_URI的固定格式为:
- '{数据库管理系统名}://{登录名}:{密码}@{IP地址}:{端口号}/{数据库名}?charset={编码格式}'
- '''
- DB_URI = 'mysql://{}:{}@{}:{}/{}?charset=utf8'.format(USERNAME,PASSWORD,HOST,PORT,DATABASE)
-
- # 设置数据库的连接URI
- SQLALCHEMY_DATABASE_URI = DB_URI
- # 设置动态追踪修改,如未设置只会提示警告
- SQLALCHEMY_TRACK_MODIFICATIONS = False
- # 设置查询时会显示原始SQL语句
- SQLALCHEMY_ECHO = True
上述配置文件设置完后,在flask程序文件下导入该文件,再用app.config.from_object
方法导入到flask对象内即可;
SQLAlchemy允许我们依据数据库的表结构来构建数据模型,即用python类的方式定义一个表模型,再通过调用create_all()方法,就可以将我们定义的所有表模型全部映射为数据库下的表;
但要注意的是每次运行create_all()这行代码时都会将所有表创建一次,导致重复创建表的问题,可以在前面添加一行drop_all()代码来删除已经创建的表;
创建表名:在用类的方式定义表模型时,使用__tablename__='<表名>'来将字符串对象设为表名,
创建列名:使用<列名>=db.Column()来将Column类的实例对象设为表的字段;我们为字段(列)指定的数据类型和约束条件,作为Column实例化时的参数;
SQLAlchemy创建表了,并可以尝试着进行插入记录的操作SQLAlchemy.session.add()
:
- from flask import Flask
- from flask_sqlalchemy import SQLAlchemy
- import flask学习.config
- from datetime import * # datatime库下的datatime类重名了
-
- app = Flask(__name__)
- app.config.from_object(flask学习.config)
-
- # 初始化一个SQLAlchemy对象(该步要在导入config后执行)
- # 实例化的同时将与数据库相关的配置读入
- db = SQLAlchemy(app)
- # 初始化app对象中与数据库相关的配置的设置,防止数据库信息泄露
- db.init_app(app)
-
- # 创建表模型类对象
- class Book(db.Model):
- __tablename__='book'
- id = db.Column(db.Integer, primary_key = True,autoincrement = True) #定义id字段
- title = db.Column(db.String(50),nullable = False) #定义title字段
- publishing_office = db.Column(db.String(100),nullable = False) #定义出版社字段
- isbn = db.Column(db.String(100),nullable = False) #定义isbn号字段
- storage_time = db.Column(db.DateTime, default = datetime.now) # 入库时间字段
-
- if __name__ == '__main__':
- # 删除数据库下的所有上述定义的表,防止重复创建
- db.drop_all()
- # 将上述定义的所有表对象映射为数据库下的表单(创建表)
- db.create_all()
-
- # 向表中插入记录:实例化-插入-提交
- book1 = Book(id='001',title='人工智能导论',publishing_office ='高等教育出版社',isbn='9787040479843')
- db.session.add(book1)
- db.session.commit()
- from flask import Flask
- from flask_sqlalchemy import SQLAlchemy
- import flask学习.config
- from datetime import * # datatime库下的datatime类重名了
-
- app = Flask(__name__)
- app.config.from_object(flask学习.config)
-
- # 初始化一个SQLAlchemy对象(该步要在导入config后执行)
- # 实例化的同时将与数据库相关的配置读入
- db = SQLAlchemy(app)
- # 初始化app对象中与数据库相关的配置的设置,防止数据库连接泄露
- db.init_app(app)
-
- # 创建表模型类对象
- class Book(db.Model):
- __tablename__='book'
- id = db.Column(db.Integer, primary_key = True,autoincrement = True) # 定义id字段
- title = db.Column(db.String(50),nullable = False) # 定义title字段
- publishing_office = db.Column(db.String(100),nullable = False) # 定义出版社字段
- price = db.Column(db.String(30), nullable=False) # 定义price号字段
- isbn = db.Column(db.String(50),nullable = False) # 定义isbn号字段
- storage_time = db.Column(db.DateTime, default = datetime.now) # 入库时间字段
-
- # 删除数据库下的所有上述定义的表,防止重复创建
- db.drop_all()
- # 将上述定义的所有表对象映射为数据库下的表单(创建表)
- db.create_all()
-
- # 添加数据的路由
- @app.route('/add')
- def add_record():
- book1 = Book(title='Python基础教程(第3版)', publishing_office ='人民邮电出版社', price = '68.30 ', isbn = '9787115474889')
- book2= Book(title='Python游戏编程快速上手第4版',publishing_office = '人民邮电出版社', price = '54.50', isbn = '9787115466419')
- book3 = Book(title='JSP+Servlet+Tomcat应用开发从零开始学',publishing_office = '清华大学出版社', price = '68.30', isbn = '9787302384496')
-
- db.session.add(book1)
- db.session.add(book2)
- db.session.add(book3)
- # 需要提交事务给数据库
- db.session.commit()
- return 'add success!'
-
- # 查找数据的路由
- @app.route('/query')
- def query_record():
- # 查找id=1的第一个对象
- result = Book.query.filter(Book.id == '1').first()
- print(result.title)
- # 查找publishing_office=人民邮电出版社的全体对象
- result_list = Book.query.filter(Book.publishing_office == '人民邮电出版社').all()
- for books in result_list:
- print(books.title)
- return 'query success!'
-
- # 修改数据的路由
- @app.route('/edit')
- def edit_record():
- # 查找id=1的第一个对象
- book1 = Book.query.filter(Book.id == '1').first()
- book1.price = 168
- # 需要提交事务给数据库
- db.session.commit()
- return 'edit success!'
-
- # 删除数据的路由
- @app.route('/delete')
- def delete_record():
- # 查找id=9的第一个对象
- book2 = Book.query.filter(Book.id == '9').first()
- db.session.delete(book2)
- # 需要提交事务给数据库
- db.session.commit()
- return 'delete success!'
-
- if __name__ == '__main__':
- 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()
;数据库实体型(表)间有3种关联关系:一对一、一对多和多对多
在SQLAlchemy中,为了在表模型间创建上述的三种关联关系,
同样要在一个表模型中通过db.ForeignKey('表模型类.属性')的方式添加外键,绑定另一个表模型的主属性(primary_key);添加外键后,
还需要使用<字段名1> = db.relationship('<多方表名>',backref=db.backref('<字段名2>')[,secondary=<Table对象名>,uselist=False])的方法来正式构建关系。
只要在实例化SQLAlchemy对象的过程中,如果参数app不为空(判断是否传入了flask对象,参数app默认值为None),那么就会调用init_app方法来初始化flask对象中数据库部分的相关配置。这时如果我们提前为flask对象导入了配置文件,init_app就无法覆写我们自定义的配置内容,也就相当于“没有起作用”。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。