flask框架学习
flask框架学习
pycharm创建项目,连接到远程gitee仓库,创建仓库flask_study,分支helloworld,
自带第一个程序"helloworld",运行程序,访问127.0.0.1/即可显示helloworld
1、配置相关
开启debug模式
app.py
# app.py内容
from flask import Flask
app = Flask(__name__)
# 设置以下内容,让json中中文正常显示
app.config['JSON_AS_ASCII'] = False
@app.route('/')
def hello_world():
return {"username": "姓名"}
if __name__ == '__main__':
app.run()
# 这种方法不方便
config.py
# 方法二:在根目录下设置一个config.py文件并添加以下内容
JSON_AS_ASCII = False
app.py
from flask import Flask
import config
app = Flask(__name__)
app.config.from_object(config) # 应用配置文件
@app.route('/')
def hello_world():
return {"username": "姓名"}
if __name__ == '__main__':
app.run()
2、url和视图映射
app.py
from flask import Flask
import config
import json
app = Flask(__name__)
app.config.from_object(config)
# 通过引用json,使用json.dumps返回请求,效率低,效果差
book_dict = [
{'id': 1, 'name': "三国", '作者': '施耐庵'},
{'id': 2, 'name': "西游", '作者': '吴承恩'},
{'id': 3, 'name': "水浒", '作者': "罗贯中"},
{'id': 4, 'name': "红楼", '作者': '曹雪芹'},
]
@app.route("/book/list/")
def book_list():
return json.dumps(book_dict)
@app.route('/')
def hello_world():
return {"username": "姓名"}
if __name__ == '__main__':
app.run()
app.py
from flask import Flask,jsonify
book_dict = [
{'id': 1, 'name': "三国", '作者': '施耐庵'},
{'id': 2, 'name': "西游", '作者': '吴承恩'},
{'id': 3, 'name': "水浒", '作者': "罗贯中"},
{'id': 4, 'name': "红楼", '作者': '曹雪芹'},
]
# 引用flask自带jsonify返回
@app.route("/book/list/")
def book_list():
return jsonify(book_dict)
app.py
from flask import Flask, jsonify
import config
app = Flask(__name__)
app.config.from_object(config)
book_dict = [
{'id': 1, 'name': "三国", '作者': '施耐庵'},
{'id': 2, 'name': "西游", '作者': '吴承恩'},
{'id': 3, 'name': "水浒", '作者': "罗贯中"},
{'id': 4, 'name': "红楼", '作者': '曹雪芹'},
]
# 在网址中输入数字,函数获取id值进行搜索
@app.route("/book/<int:book_id>")
def book_detail(book_id):
for book in book_dict:
if book_id == book['id']:
return jsonify(book)
return "没找到"
@app.route("/book/list/")
def book_list():
return jsonify(book_dict)
@app.route('/')
def hello_world():
return {"username": "姓名"}
if __name__ == '__main__':
app.run()
app.py
from flask import Flask, jsonify, url_for
import config
app = Flask(__name__)
app.config.from_object(config)
book_dict = [
{'id': 1, 'name': "三国", '作者': '施耐庵'},
{'id': 2, 'name': "西游", '作者': '吴承恩'},
{'id': 3, 'name': "水浒", '作者': "罗贯中"},
{'id': 4, 'name': "红楼", '作者': '曹雪芹'},
]
@app.route("/book/<int:book_id>")
def book_detail(book_id):
for book in book_dict:
if book_id == book['id']:
return jsonify(book)
return "没找到"
@app.route("/book/list/")
def book_list():
# 导入url_for,向book_dict中添加对用的url/id
for book in book_dict:
book['url'] = url_for("book_detail", book_id=book['id'])
return jsonify(book_dict)
@app.route('/')
def hello_world():
return {"username": "姓名"}
if __name__ == '__main__':
app.run()
3、method请求
1、如果只是需要从服务器获取数据,一般都是用GET请求
2、如果前端需要把数据发送给服务器,一般是POST请求
3、在装饰器里直接加入 methods = ['GET',"POST"],也可以指定某一种请求方式
Request对象的重要属性如下所列:
Form - 它是一个字典对象,包含表单参数及其值的键和值对。
args - 解析查询字符串的内容,它是问号(?)之后的URL的一部分。
Cookies - 保存Cookie名称和值的字典对象。
files - 与上传文件有关的数据。
method - 当前请求方法。
————————————————
版权声明:本文为CSDN博主「爱编程的喵汪人」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/qq_42415326/article/details/90374936
@app.route("/book/<int:book_id>", methods=['POST',"GET"])
def book_detail(book_id):
for book in book_dict:
if book_id == book['id']:
return jsonify(book)
return "没找到"
# 参数的传递形式
# 1、作为url的组成方式: /book/1
# 2、查询字符串 /book?id=1
app.py
redirect(url_for("hellow_world")) # 重定向-hello_world的函数的网址,
user_id = request.args.get('id') # 使用get方法获得网址里输入的id
from flask import Flask, jsonify, url_for, redirect, request
import config
@app.route("/profile")
def profile():
# 参数的传递形式
# 1、作为url的组成方式: /book/1
# 2、查询字符串 /book?id=1
user_id = request.args.get('id')
if user_id:
return "用户个人中心"
else:
return redirect(url_for('hello_world'))
@app.route('/')
def hello_world():
return {"username": "姓名"}
4、jinjia2模板
模板概述
所有HTML文件存放在templates中
render_template # 此方法默认从templates中寻找
# 可以更改,一般不更改
app.py
向render_template中传参数,并在about中显示出来
from flask import Flask, render_template
app = Flask(__name__)
@app.route('/about/')
def about():
# 默认在templates中寻找,一般不更改
context = {
'username': 'name',
'age': 'age',
}
return render_template('about.html', **context)
@app.route('/')
def hello_world():
return 'Hello World!'
if __name__ == '__main__':
app.run()
about.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>关于我们</title>
</head>
<body>
<h1>这只是一个简单的模板文件</h1>
<p>{{ username }}</p>
<p>{{ age }}</p>
</body>
</html>
概述总结:
- 模板文件,也就是html文件,需要放到templates文件夹下,当然在
Flask(__name__,template_folder)
来修改模板的地址,但是不推荐。 - 通过
render_template
来渲染模板。 - 如果想要传递变量到模板中,那么可以把变量定义成字典,然后在
render_template
中,通过关键字参数的方式传递过去。render_template('',**context)
。
jinjia2模板过滤器
{{ username|length }}
过滤器是通过管道符号(|
)进行使用的,例如:{{ name|length }}
,将返回name的长度。过滤器相当于是一个函数,把当前的变量传入到过滤器中,然后过滤器根据自己的功能,再返回相应的值,之后再将结果渲染到页面中。Jinja2
中内置了许多过滤器,在这里可以看到所有的过滤器,现对一些常用的过滤器进行讲解:
常用的过滤器
-
abs(value)
:返回一个数值的绝对值。 例如:-1|abs
。 -
default(value,default_value,boolean=false)
:如果当前变量没有值,则会使用参数中的值来代替。name|default('xiaotuo')
——如果name不存在,则会使用xiaotuo
来替代。boolean=False
默认是在只有这个变量为undefined
的时候才会使用default
中的值,如果想使用python
的形式判断是否为false
,则可以传递boolean=true
。也可以使用or
来替换。 -
escape(value)或e
:转义字符,会将<
、>
等符号转义成HTML中的符号。例如:content|escape
或content|e
。 -
first(value)
:返回一个序列的第一个元素。names|first
。 -
format(value,*arags,**kwargs)
:格式化字符串。例如以下代码:{{ "%s" - "%s"|format('Hello?',"Foo!") }}
将输出:Helloo? - Foo!
-
last(value)
:返回一个序列的最后一个元素。示例:names|last
。 -
length(value)
:返回一个序列或者字典的长度。示例:names|length
。 -
join(value,d=u'')
:将一个序列用d
这个参数的值拼接成字符串。 -
safe(value)
:如果开启了全局转义,那么safe
过滤器会将变量关掉转义。示例:content_html|safe
。 -
int(value)
:将值转换为int
类型。 -
float(value)
:将值转换为float
类型。 -
lower(value)
:将字符串转换为小写。 -
upper(value)
:将字符串转换为小写。 -
replace(value,old,new)
: 替换将old
替换为new
的字符串。 -
truncate(value,length=255,killwords=False)
:截取length
长度的字符串。 -
striptags(value)
:删除字符串中所有的HTML标签,如果出现多个空格,将替换成一个空格。 -
trim
:截取字符串前面和后面的空白字符。 -
string(value)
:将变量转换成字符串。 -
wordcount(s)
:计算一个长字符串中单词的个数。
控制语句
所有的控制语句都是放在{% ... %}
中,并且有一个语句{% endxxx %}
来进行结束,Jinja
中常用的控制语句有if/for..in..
,现对他们进行讲解:
-
if
:if语句和python
中的类似,可以使用>,<,<=,>=,==,!=
来进行判断,也可以通过and,or,not,()
来进行逻辑合并操作,以下看例子:{% if kenny.sick %} Kenny is sick. {% elif kenny.dead %} You killed Kenny! You bastard!!! {% else %} Kenny looks okay --- so far {% endif %}
-
for...in...
:for
循环可以遍历任何一个序列包括列表、字典、元组。并且可以进行反向遍历,以下将用几个例子进行解释:-
普通的遍历:
<ul> {% for user in users %} <li>{{ user.username|e }}</li> {% endfor %} </ul>
-
遍历字典:
<dl> {% for key, value in my_dict.iteritems() %} <dt>{{ key|e }}</dt> <dd>{{ value|e }}</dd> {% endfor %} </dl>
-
如果序列中没有值的时候,进入
else
:<ul> {% for user in users %} <li>{{ user.username|e }}</li> {% else %} <li><em>no users found</em></li> {% endfor %} </ul>
-
并且Jinja
中的for
循环还包含以下变量,可以用来获取当前的遍历状态:
变量 | 描述 |
---|---|
loop.index | 当前迭代的索引(从1开始) |
loop.index0 | 当前迭代的索引(从0开始) |
loop.first | 是否是第一次迭代,返回True或False |
loop.last | 是否是最后一次迭代,返回True或False |
loop.length | 序列的长度 |
另外,不可以使用continue
和break
表达式来控制循环的执行。
模板继承
不同于django,flask中继承时,引入css文件的方法是,使用url_for
{% block head %}
<link href="{{ url_for('static', filename = 'css/index.css') }}" rel="stylesheet">
{% endblock %}
5、视图高级
蓝图
在项目根目录创建一个python包,apps
在apps中,创建三个py文件分别为,book.py course.py user.py
book.py
from flask import Blueprint
# url_prefix设置网络地址前缀 1270.0.0.1:5000/book
bp = Blueprint('book', __name__, url_prefix='/book/')
@bp.route('/list/')
def book_list():
return '图书列表'
course.py
from flask import Blueprint
# url_prefix设置网络地址前缀 1270.0.0.1:5000/book
bp = Blueprint('course', __name__, url_prefix='/course/')
@bp.route('/list/')
def course_list():
return '课程列表'
user.py
from flask import Blueprint
# url_prefix设置网络地址前缀 1270.0.0.1:5000/book
bp = Blueprint('user', __name__, url_prefix='/user/')
@bp.route('/list/')
def user_list():
return '用户列表'
在app.py中导入三个文件
使用函数register_blueprint拼接
from flask import Flask
from apps import book, course, user
app = Flask(__name__)
# 注册蓝图
app.register_blueprint(book.bp)
app.register_blueprint(user.bp)
app.register_blueprint(course.bp)
@app.route('/')
def hello_world():
return 'Hello World!'
if __name__ == '__main__':
app.run(debug=True)
说明:
在apps中的每一个py文件,如果要重定向到某个html文件,写法和app.py一样,默认还是文件夹templates和static
6、数据库插件sqlalchemy
Flask-SQLAlchemy笔记
一、SQLAlchemy和Flask-SQLAlchemy的区别:
- SQLAlchemy:是一个独立的ORM框架,可以独立于Flask存在,也可以在其他项目中使用,比如在Django中。
- Flask-SQLAlchemy:对SQLAlchemy的一个封装,能够更适合在flask中使用。
一、安装和验证:
- 安装连接数据库的库:pip install pymysql
- 安装:pip install flask-sqlalchemy
二、连接数据库:
# 数据库的配置变量
HOSTNAME = '127.0.0.1'
PORT = '3306'
DATABASE = 'xt_flask'
USERNAME = 'root'
PASSWORD = 'root'
DB_URI = 'mysql+pymysql://{}:{}@{}:{}/{}'.format(USERNAME,PASSWORD,HOSTNAME,PORT,DATABASE)
app.config['SQLALCHEMY_DATABASE_URI'] = DB_URI
app.py
from flask import Flask
import pymysql
from flask_sqlalchemy import SQLAlchemy
app = Flask(__name__)
# 数据库的配置变量
HOSTNAME = '127.0.0.1'
PORT = '3306'
DATABASE = 'staff_info'
USERNAME = 'root'
PASSWORD = 'wocaonima'
DB_URI = 'mysql+pymysql://{}:{}@{}:{}/{}?charset=utf8'.format(USERNAME, PASSWORD, HOSTNAME, PORT, DATABASE)
app.config['SQLALCHEMY_DATABASE_URI'] = DB_URI
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = True
db = SQLAlchemy(app)
@app.route('/')
def hello_world():
# 写个测试代码验证是否研究成功
engine = db.get_engine()
# conn = engine.connect()
# conn.close()
with engine.connect() as conn:
result = conn.execute('select 1;')
print(result.fetchone())
return 'Hello World!'
if __name__ == '__main__':
app.run(debug=True)
三、创建模型:
app.py
数据库操作:
from flask import Flask
import pymysql
from flask_sqlalchemy import SQLAlchemy
app = Flask(__name__)
# 数据库的配置变量
HOSTNAME = '127.0.0.1'
PORT = '3306'
DATABASE = 'flask_test'
USERNAME = 'root'
PASSWORD = 'wocaonima'
DB_URI = 'mysql+pymysql://{}:{}@{}:{}/{}?charset=utf8'.format(USERNAME, PASSWORD, HOSTNAME, PORT, DATABASE)
app.config['SQLALCHEMY_DATABASE_URI'] = DB_URI
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = True
db = SQLAlchemy(app)
# 定义ORM模型
class Article(db.Model):
__tablename__ = 'article'
id = db.Column(db.Integer, primary_key=True, autoincrement=True)
title = db.Column(db.String(200), nullable=False)
content = db.Column(db.Text, nullable=False)
db.create_all()
@app.route('/')
def hello_world():
# 写个测试代码验证是否研究成功
engine = db.get_engine()
# conn = engine.connect()
# conn.close()
with engine.connect() as conn:
result = conn.execute('select 1;')
print(result.fetchone())
return 'Hello World!'
@app.route('/article')
def article_view():
# 1、添加数据
article = Article()
article.title = '骆驼祥子'
article.content = '虎妞'
db.session.add(article)
# 提交
db.session.commit()
return '成功'
@app.route('/article/1')
def article_query():
# 1、查询数据
article = Article().query.filter_by(id=1)[0]
print(article.title)
return article.title
@app.route('/article/upgrade')
def article_upgrade():
# 1、查询数据,返回一个类对象
article = Article().query.filter_by(id=1)[0]
article.title = '骆驼老顾'
db.session.commit()
return article.title
@app.route('/article/delete')
def article_delete():
# 1、删除,返回一个类对象
article = Article().query.filter_by(id=1).delete()
db.session.commit()
return "article.title"
if __name__ == '__main__':
app.run(debug=True)
设置外键
author_id = db.Column(db.Integer, db.ForeignKey("user.id")) # 设置外键
数据库迁移
pip install flask-migrate #先安装第三方模块
from flask import Flask
from flask_sqlalchemy import SQLAlchemy
from flask_migrate import Migrate
app = Flask(__name__)
# 数据库的配置变量
HOSTNAME = '127.0.0.1'
PORT = '3306'
DATABASE = 'flask_test'
USERNAME = 'root'
PASSWORD = 'wocaonima'
DB_URI = 'mysql+pymysql://{}:{}@{}:{}/{}?charset=utf8'.format(USERNAME, PASSWORD, HOSTNAME, PORT, DATABASE)
app.config['SQLALCHEMY_DATABASE_URI'] = DB_URI
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = True
db = SQLAlchemy(app)
# 迁移数据库
migrate = Migrate(app, db)
终端输入 :
flask db init
flask db migrate -m "first commit"
flask db upgrade
第二次迁移,例如向user加一个password字段
flask db migrate -m "add password to user"
flask db upgrade
第三次迁移,例如从user删除password字段
flask db migrate -m "remove password from user"
flask db upgrade
四、表关系:
1. 一对多 app.py:
创建表时,设置一个外键和relationship
from flask import Flask
import pymysql
from flask_sqlalchemy import SQLAlchemy
app = Flask(__name__)
# 数据库的配置变量
HOSTNAME = '127.0.0.1'
PORT = '3306'
DATABASE = 'flask_test'
USERNAME = 'root'
PASSWORD = 'wocaonima'
DB_URI = 'mysql+pymysql://{}:{}@{}:{}/{}?charset=utf8'.format(USERNAME, PASSWORD, HOSTNAME, PORT, DATABASE)
app.config['SQLALCHEMY_DATABASE_URI'] = DB_URI
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = True
db = SQLAlchemy(app)
# 定义ORM模型
class User(db.Model):
__tablename__ = 'user'
id = db.Column(db.Integer, primary_key=True, autoincrement=True)
username = db.Column(db.String(200), nullable=False)
# 定义ORM模型
class Article(db.Model):
__tablename__ = 'article'
id = db.Column(db.Integer, primary_key=True, autoincrement=True)
title = db.Column(db.String(200), nullable=False)
content = db.Column(db.Text, nullable=False)
author_id = db.Column(db.Integer, db.ForeignKey("user.id")) # 设置外键
# 通过外键绑定关系,第一个参数和另一个表的名字一样, backref代表反向引用,即被访问时的字段名称, relationship的前提是必须已经有外键
author = db.relationship("User", backref='articles')
# 不迁移就得先删除所有表然后再创建
db.drop_all()
db.create_all()
@app.route("/one2many/")
def one2many():
article1 = Article(title='刚忒1', content='xxx')
article2 = Article(title='刚忒2', content='xxx')
user = User(username="强子")
article1.author = user
article2.author = user
db.session.add(article1, article2) # 添加一个两个都添加进去了
db.session.commit()
print(user.articles)
return 'success'
if __name__ == '__main__':
app.run(debug=True)
2. 一对一 app.py:
from flask import Flask
import pymysql
from flask_sqlalchemy import SQLAlchemy
app = Flask(__name__)
# 数据库的配置变量
HOSTNAME = '127.0.0.1'
PORT = '3306'
DATABASE = 'flask_test'
USERNAME = 'root'
PASSWORD = 'wocaonima'
DB_URI = 'mysql+pymysql://{}:{}@{}:{}/{}?charset=utf8'.format(USERNAME, PASSWORD, HOSTNAME, PORT, DATABASE)
app.config['SQLALCHEMY_DATABASE_URI'] = DB_URI
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = True
db = SQLAlchemy(app)
# 定义ORM模型
class User(db.Model):
__tablename__ = 'user'
id = db.Column(db.Integer, primary_key=True, autoincrement=True)
username = db.Column(db.String(200), nullable=False)
class UserExtension(db.Model):
__tablename__ = 'user_extension'
id = db.Column(db.Integer, primary_key=True, autoincrement=True)
school = db.Column(db.String(100))
user_id = db.Column(db.Integer, db.ForeignKey('user.id'))
# 反向引发是,uselist=false,禁止使用列表,即达成一对一
user = db.relationship("User", backref=db.backref('extension', uselist=False))
# 定义ORM模型
class Article(db.Model):
__tablename__ = 'article'
id = db.Column(db.Integer, primary_key=True, autoincrement=True)
title = db.Column(db.String(200), nullable=False)
content = db.Column(db.Text, nullable=False)
author_id = db.Column(db.Integer, db.ForeignKey("user.id")) # 设置外键
# 通过外键绑定关系,第一个参数和另一个表的名字一样, backref代表反向引用,即被访问时的字段名称, relationship的前提是必须已经有外键
author = db.relationship("User", backref='articles')
# 不迁移就得先删除所有表然后再创建
db.drop_all()
db.create_all()
@app.route("/o2o/")
def o2o():
user = User(username='学霸')
extension = UserExtension(school="北大")
user.extension = extension
db.session.add(user)
db.session.commit()
return 'das'
@app.route("/one2many/")
def one2many():
article1 = Article(title='刚忒1', content='xxx')
article2 = Article(title='刚忒2', content='xxx')
user = User(username="强子")
article1.author = user
article2.author = user
db.session.add(article1, article2) # 添加一个两个都添加进去了
db.session.commit()
print(user.articles)
return 'success'
if __name__ == '__main__':
app.run(debug=True)
3. 多对多:
7、代码重构
创建一个单独的
app.config.from_object(config) # 导入配置文件
迁移的时候,容易引起db的循环,解决方法为:将db放在一个单独的py文件exts,先不要绑定db,待app.py读取到配置好文件,再进行数据库和app的绑定,如下:
# 把app绑定到db上
db.init_app(app)
8、cookie和session
cookie和session
cookie
:在网站中,http请求是无状态的。也就是说即使第一次和服务器连接后并且登录成功后,第二次请求服务器依然不能知道当前请求是哪个用户。cookie
的出现就是为了解决这个问题,第一次登录后服务器返回一些数据(cookie)给浏览器,然后浏览器保存在本地,当该用户发送第二次请求的时候,就会自动的把上次请求存储的cookie
数据自动的携带给服务器,服务器通过浏览器携带的数据就能判断当前用户是哪个了。cookie
存储的数据量有限,不同的浏览器有不同的存储大小,但一般不超过4KB。因此使用cookie
只能存储一些小量的数据。session
: session和cookie的作用有点类似,都是为了存储用户相关的信息。不同的是,cookie
是存储在本地浏览器,session
是一个思路、一个概念、一个服务器存储授权信息的解决方案,不同的服务器,不同的框架,不同的语言有不同的实现。虽然实现不一样,但是他们的目的都是服务器为了方便存储数据的。session
的出现,是为了解决cookie
存储数据不安全的问题的。cookie
和session
结合使用:web
开发发展至今,cookie
和session
的使用已经出现了一些非常成熟的方案。在如今的市场或者企业里,一般有两种存储方式:- 存储在服务端:通过
cookie
存储一个session_id
,然后具体的数据则是保存在session
中。如果用户已经登录,则服务器会在cookie
中保存一个session_id
,下次再次请求的时候,会把该session_id
携带上来,服务器根据session_id
在session
库中获取用户的session
数据。就能知道该用户到底是谁,以及之前保存的一些状态信息。这种专业术语叫做server side session
。存储在服务器的数据会更加的安全,不容易被窃取。但存储在服务器也有一定的弊端,就是会占用服务器的资源,但现在服务器已经发展至今,一些session
信息还是绰绰有余的。 - 将
session
数据加密,然后存储在cookie
中。这种专业术语叫做client side session
。flask
采用的就是这种方式,但是也可以替换成其他形式。
- 存储在服务端:通过
flask中使用cookie和session
-
cookies:在
Flask
中操作
cookie
,是通过
response
对象来操作,可以在
response
返回之前,通过
response.set_cookie
来设置,这个方法有以下几个参数需要注意:
- key:设置的cookie的key。
- value:key对应的value。
- max_age:改cookie的过期时间,如果不设置,则浏览器关闭后就会自动过期。
- expires:过期时间,应该是一个
datetime
类型。 - domain:该cookie在哪个域名中有效。一般设置子域名,比如
cms.example.com
。 - path:该cookie在哪个路径下有效。
-
session:
Flask
中的session
是通过from flask import session
。然后添加值key和value进去即可。并且,Flask
中的session
机制是将session
信息加密,然后存储在cookie
中。专业术语叫做client side session
。
app.py
from flask import Flask, Response, request, session
app = Flask(__name__)
app.config["SECRET_KEY"] = '123'
@app.route('/set_cookie/')
def set_cookie():
response = Response("cookie 设置")
response.set_cookie("user_id", 'xxx')
return response
@app.route("/set_session")
def set_session():
session['username'] = 'name'
return 'set_session'
@app.route("/get_session")
def get_session():
username = session.get('username')
print(username)
return 'sadas'
@app.route('/get_cookie/')
def get_cookie():
user_id = request.cookies.get("user_id")
print(user_id)
return '获取cookie'
@app.route('/')
def hello_world():
return 'Hello World!'
if __name__ == '__main__':
app.run()
9、Flask-WTF表单验证
Flask-WTF
是简化了WTForms
操作的一个第三方库。WTForms
表单的两个主要功能是验证用户提交数据的合法性以及渲染模板。当然还包括一些其他的功能:CSRF保护
,文件上传等。安装Flask-WTF
默认也会安装WTForms
,因此使用以下命令来安装Flask-WTF
:
pip install flask-wtf
一、表单验证:
安装完Flask-WTF
后。来看下第一个功能,就是用表单来做数据验证,现在有一个forms.py
文件,然后在里面创建一个RegistForm
的注册验证表单:
class RegistForm(Form):
name = StringField(validators=[length(min=4,max=25)])
email = StringField(validators=[email()])
password = StringField(validators=[DataRequired(),length(min=6,max=10),EqualTo('confirm')])
confirm = StringField()
在这个里面指定了需要上传的参数,并且指定了验证器,比如name
的长度应该在4-25
之间。email
必须要满足邮箱的格式。password
长度必须在6-10
之间,并且应该和confirm
相等才能通过验证。
写完表单后,接下来就是regist.html
文件:
<form action="/regist/" method="POST">
<table>
<tr>
<td>用户名:</td>
<td><input type="text" name="name"></td>
</tr>
<tr>
<td>邮箱:</td>
<td><input type="email" name="email"></td>
</tr>
<tr>
<td>密码:</td>
<td><input type="password" name="password"></td>
</tr>
<tr>
<td>确认密码:</td>
<td><input type="password" name="confirm"></td>
</tr>
<tr>
<td></td>
<td><input type="submit" value="提交"></td>
</tr>
</table>
</form>
再来看视图函数regist
:
@app.route('/regist/',methods=['POST','GET'])
def regist():
form = RegistForm(request.form)
if request.method == 'POST' and form.validate():
user = User(name=form.name.data,email=form.email.data,password=form.password.data)
db.session.add(user)
db.session.commit()
return u'注册成功!'
return render_template('regist.html')
RegistForm
传递的是request.form
进去进行初始化,并且判断form.validate
会返回用户提交的数据是否满足表单的验证。
二、渲染模板:
form
还可以渲染模板,让你少写了一丢丢的代码,比如重写以上例子,RegistForm
表单代码如下:
class RegistForm(Form):
name = StringField(u'用户名:',validators=[length(min=4,max=25)])
email = StringField(u'邮箱:'validators=[email()])
password = StringField(u'密码:',validators=[DataRequired(),length(min=6,max=10),EqualTo('confirm')])
confirm = StringField(u'确认密码:')
以上增加了第一个位置参数,用来在html文件中,做标签提示作用。
在app
中的视图函数中,修改为如下:
@app.route('/regist/',methods=['POST','GET'])
def regist():
form = RegistForm(request.form)
if request.method == 'POST' and form.validate():
user = User(name=form.name.data,email=form.email.data,password=form.password.data)
db.session.add(user)
db.session.commit()
return u'注册成功!'
return render_template('regist.html',form=form)
以上唯一的不同是在渲染模板的时候传入了form
表单参数进去,这样在模板中就可以使用表单form
变量了。
接下来看下regist.html
文件:
<form action="/regist/" method="POST">
<table>
<tr>
<td>{{ form.name.label }}</td>
<td>{{ form.name() }}</td>
</tr>
<tr>
<td>{{ form.email.label }}</td>
<td>{{ form.email() }}</td>
</tr>
<tr>
<td>{{ form.password.label }}</td>
<td>{{ form.password() }}</td>
</tr>
<tr>
<td>{{ form.confirm.label }}</td>
<td>{{ form.confirm() }}</td>
</tr>
<tr>
<td></td>
<td><input type="submit" value="提交"></td>
</tr>
</table>
</form>
7、文件上传
用 Flask 处理文件上传非常简单。需要在HTML表单form中,确保设置其enctype属性为“multipart / form-data”,就可以将文件发布到URL,URL处理程序从request.files[]对象中提取文件,并将其保存到所需的位置。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· .NET10 - 预览版1新功能体验(一)