文章目录
一、路由
路由:处理URL和视图函数的这种关系,访问index则执行index视图函数。
from flask import Flask app = Flask(__name__) @app.route('/') def hello_world(): return 'Hello World!' # 可变,动态 @app.route('/user/
'
) def show_user(username): return f'我是{
username}' @app.route('/post/
'
) def show_post_indo(post_id): return f'post_id是{
post_id}' if __name__ == '__main__': app.run()
二、常用的HTTP方法
三、构造URL函数
from flask import Flask, url_for app = Flask(__name__) @app.route('/') def hello_world(): return 'Hello World!' @app.route('/user/
'
) def show_user(username): return f'我是{
username}' @app.route('/test/') def test(): return url_for('show_user', username='Andy') # (函数名,参数赋值) if __name__ == '__main__': app.run()
四、MVC设计模型
controller是调度中心,每一个表就是一个model。例如,订单表就是订单模型,view是视图层,里面存有多个模板。
五、渲染模板
render_template(模板名称,函数赋值)
template中user.html
DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title
title>
head> <body> <h1>SpaceX?课堂
h1> <p>欢迎来到SpaceX课堂,我是{
{ name }}
p>
body>
html>
app.py
from flask import Flask, url_for, render_template app = Flask(__name__) @app.route('/') def index(): return render_template('index.html') # 静态 @app.route('/user1/') def show_user1(): return render_template('user.html', name='Max') # 动态 @app.route('/user2/
'
) def show_user2(user): return render_template('user.html', name=user) if __name__ == '__main__': app.run()
六、模板变量
template中index.html
DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title
title>
head> <body> <p>欢迎来到SpaceX课堂,我是{
{ dict_val['name'] }},年龄{
{ dict_val['age'] }}
p> <ul> <li> {
{ list_val[0] }}
li> <li> {
{ list_val[1] }}
li> <li> {
{ list_val[2] }}
li>
ul> <p> {
{ user.name }} {
{ user.get_info() }}
p>
body>
html>
app.py
from flask import Flask, url_for, render_template app = Flask(__name__) app.debug = True class User(): def __init__(self, name, age): self.name = name self.age = age def get_info(self): return f'我的名字是{
self.name},年龄{
self.name}' @app.route('/') def index(): dict_val = {
'name': 'andy', 'age': 18} list_val = [i for i in range(10)] user = User('andy', 18) return render_template('index.html', dict_val=dict_val, list_val=list_val, user=user) if __name__ == '__main__': app.run()
七、模板过滤器
capitalize, safe, striptags的使用:
flask为了安全会把所有标签视为字符串,除非用过滤器safe确定其安全,才不转义为字符串。
template中index.html
DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title
title>
head> <body> <p>欢迎来到SpaceX课堂,我是{
{ dict_val['name']|capitalize }},年龄{
{ dict_val['age'] }}
p> <ul> <li> {
{ list_val[0] }}
li> <li> {
{ list_val[1] }}
li> <li> {
{ list_val[2] }}
li>
ul> <p> {
{ user.get_info()|striptags}}
p> <p> {
{ user.name }} {
{ user.get_info()|safe}}
p>
body>
html>
app.py
from flask import Flask, url_for, render_template app = Flask(__name__) app.debug = True class User(): def __init__(self, name, age): self.name = name self.age = age def get_info(self): return f'我的名字是
{
self.name},年龄{
self.name}'
@app.route('/') def index(): dict_val = {
'name': 'andy', 'age': 18} list_val = [i for i in range(10)] user = User('andy', 18) return render_template('index.html', dict_val=dict_val, list_val=list_val, user=user) # 参数模板名称 if __name__ == '__main__': app.run()
八、模板控制结构
template中index.html
DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title
title>
head> <body> <p>欢迎来到SpaceX课堂,我是{
{ dict_val['name']|capitalize }},年龄{
{ dict_val['age'] }}
p> <ul> {% for item in list_val %} <li> {
{ item }} {% for i in range(2) %} 测试 {% endfor %}
li> {% endfor %}
ul> <p> {% if user.name == 'andy' %} 欢迎管理员登录 {% elif user.name == 'daxiong' %} 欢迎版主登录 {% else %} 欢迎{
{ user.name }}登录 {% endif %}
p>
body>
html>
app.py
from flask import Flask, render_template app = Flask(__name__) app.debug = True class User(): def __init__(self, name, age): self.name = name self.age = age def get_info(self): return f'我的名字是
{
self.name},年龄{
self.name}'
@app.route('/') def index(): dict_val = {
'name': 'andy', 'age': 18} list_val = [i for i in range(10)] user = User('andy', 18) return render_template('index.html', dict_val=dict_val, list_val=list_val, user=user) # 参数模板名称 if __name__ == '__main__': app.run()
九、模板的继承
子模板中:
{% extends ‘base.html’ %}
{% block title %} 填空… {% endblock %}
{% block body %} 填空… {% endblock %}
template中base.html
DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>{% block title %}父模板{% endblock %}
title>
head> <body> {% block nav %} 首页|商品分类|关于我们|联系我们 {% endblock %} {% block body %} {% endblock %} {% block footer %} 购物流程 会员介绍 生活旅行/团购 常见问题 大家电 联系客服 {% endblock %}
body>
html>
template中index.html
{% extends 'base.html' %}
{% block title %}子模板{% endblock %}
{% block body %}
<p>欢迎来到SpaceX课堂,我是{
{ dict_val['name']|capitalize }},年龄{
{ dict_val['age'] }}
p> <ul> {% for item in list_val %} <li> {
{ item }} {% for i in range(2) %} 测试 {% endfor %}
li> {% endfor %}
ul> <p> {% if user.name == 'andy' %} 欢迎管理员登录 {% elif user.name == 'daxiong' %} 欢迎版主登录 {% else %} 欢迎{
{ user.name }}登录 {% endif %}
p> {% endblock %}
十、Web表单
注意:
- action表示提交到哪里
- 注册method不用get,因为会传到URL中,不安全
- 不会用到js,只用form.py和views.py视图函数
- submit按钮可整表提交,不需绑定按钮
template中login.html
DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>login
title>
head> <body> <form action="" method="post"> <div> <label>用户名
label> <input type="text" name="username" value="">
div> <div> <label>密码
label> <input type="password" name="password" value="">
div> <button>提交
button>
form>
body>
html>
app.py
from flask import Flask, render_template app = Flask(__name__) app.debug = True @app.route('/login') def login(): return render_template('login.html') if __name__ == '__main__': app.run()
十一、WTForms实现表单验证
forms – app – html 三件套
forms.py
from wtforms import Form, StringField, PasswordField, SubmitField from wtforms.validators import DataRequired, Length class LoginForm(Form): username = StringField(label='用户名', validators=[ DataRequired('请填写用户名'), Length(min=6, max=50, message='用户名长度在6-50个字符之间') ]) password = PasswordField(label='密码', validators=[ DataRequired('请填写密码'), Length(min=6, max=50, message='密码在6-50') ]) submit = SubmitField(label='提交')
app.py
from flask import Flask, render_template, request from forms import LoginForm app = Flask(__name__) app.debug = True @app.route('/', methods=['GET', 'POST']) def login(): form = LoginForm(request.form) # request.form是用户提交的表单内容 if request.method == 'POST' and form.validate(): pass return render_template('login.html', form=form) if __name__ == '__main__': app.run()
templates中login.html
DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>login
title>
head> <body> <form action="" method="post"> <div> {
{ form.username.label }} {
{ form.username }} {% for error in form.username.errors %} {
{ error }} {% endfor %}
div> <div> {
{ form.password.label }} {
{ form.password }} {% for error in form.password.errors %} {
{ error }} {% endfor %}
div> {
{ form.submit }}
form>
body>
html>
十二、防止CSRF攻击 和 flask_wtf的简化
【注意?】!!!!!的位置是基于十一章改变/多加的
- 防止CSRF攻击:每次访问一个服务器,给用户发token,提交表单时,也提交token。假的网站不能高仿token,所以利用token可以防止CSRF攻击。
- flask_wtf的简化:
| 包 | 模块 | 情况 |
|---|---|---|
| wtforms | Form | |
| flask_wtf | FlaskForm | flask对wtforms做出精简,更适合flask框架 |
| flask_sqlalchemy | SQLAlchemy | 数据库相关的 |
forms – app – html 三件套
forms.py
from wtforms import StringField, PasswordField, SubmitField from wtforms.validators import DataRequired, Length from flask_wtf import FlaskForm # 简化!!!!! class LoginForm(FlaskForm): # 简化!!!!! username = StringField(label='用户名', validators=[ DataRequired('请填写用户名'), Length(min=6, max=50, message='用户名长度在6-50个字符之间') ]) password = PasswordField(label='密码', validators=[ DataRequired('请填写密码'), Length(min=6, max=50, message='密码在6-50') ]) submit = SubmitField(label='提交')
app.py
from flask import Flask, render_template, request from forms import LoginForm app = Flask(__name__) app.debug = True app.config['SECRET_KEY'] = 'spaceX?' @app.route('/', methods=['GET', 'POST']) def login(): form = LoginForm(request.form) # request.form是用户提交的表单内容 # if request.method == 'POST' and form.validate(): if form.validate_on_submit(): # 简化!!!!!! pass return render_template('login.html', form=form) if __name__ == '__main__': app.run()
templates中login.html
DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>login
title>
head> <body> <form action="" method="post"> {
{ form.csrf_token }} # token !!!!!! <div> {
{ form.username.label }} {
{ form.username }} {% for error in form.username.errors %} {
{ error }} {% endfor %}
div> <div> {
{ form.password.label }} {
{ form.password }} {% for error in form.password.errors %} {
{ error }} {% endfor %}
div> {
{ form.submit }}
form>
body>
html>
十三、flask_sqlalchemy 利用ORM创建数据表
ORM: 将数据库转化为python对象,不用再记忆SQL语句
from flask import Flask, render_template, request from flask_sqlalchemy import SQLAlchemy import pymysql app = Flask(__name__) app.debug = True # 1. 配置app参数 app.config['SECRET_KEY'] = 'spaceX' app.config['SQLALCHEMY_DATABASE_URI'] = ( 'mysql+pymysql://用户名:密码@localhost/flask_demo?charset=utf8mb4' ) app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = True # 2. 定义数据库 db = SQLAlchemy(app) # 3. 定义数据库表的ORM类 class User(db.Model): id = db.Column(db.Integer, autoincrement=True, primary_key=True) username = db.Column(db.String(80), unique=True, nullable=False) email = db.Column(db.String(120), unique=True, nullable=False) password = db.Column(db.String(20), nullable=False) def __repr__(self): return f"
is
{
self.username}" # 4. 创建数据库中的所有表 db.create_all() @app.route('/') def hello_world(): # put application's code here return 'Hello World!' if __name__ == '__main__': app.run()
十四、数据表关系
from flask import Flask, render_template, request from flask_sqlalchemy import SQLAlchemy import pymysql app = Flask(__name__) app.debug = True app.config['SECRET_KEY'] = 'spaceX' app.config['SQLALCHEMY_DATABASE_URI'] = ( 'mysql+pymysql://root:Root8834@localhost/flask_demo?charset=utf8mb4' ) app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = True db = SQLAlchemy(app) class User(db.Model): __tablename__ = 'user' id = db.Column(db.Integer, autoincrement=True, primary_key=True) username = db.Column(db.String(80), unique=True, nullable=False) email = db.Column(db.String(120), unique=True, nullable=False) password = db.Column(db.String(20), nullable=False) articles = db.relationship('Article', backref='user') # 关联 def __repr__(self): return f"
is
{
self.username}" class Article(db.Model): id = db.Column(db.Integer, autoincrement=True, primary_key=True) title = db.Column(db.String(80), unique=True, nullable=False) password = db.Column(db.String(120), nullable=False) user_id = db.Column(db.Integer, db.ForeignKey('user.id')) # 定义外键 def __repr__(self): return f"
is
{
self.title}" db.create_all() @app.route('/') def hello_world(): # put application's code here return 'Hello World!' if __name__ == '__main__': app.run()
十五、Flask_SQLAlchemy操作数据库 — 增删改查
增:
@app.route('/') def hello_world(): # 1. 添加数据 user = User(username='Silva72', email='@.com', password='') db.session.add(user) db.session.commit() return 'Hello World!'
查:
@app.route('/') def hello_world(): # 1. 添加数据 # user = User(username='Silva72', email='@.com', password='') # db.session.add(user) # db.session.commit() # 2. 查找数据 users = User.query.all() for user in users: print(user.id) print(user.username) print(User.query.get(2)) print(User.query.count()) print(User.query.filter_by(id=1)[0].email) print(User.query.get_or_404(2)) return 'Hello World!'
改:
@app.route('/') def hello_world(): # put application's code here # 1. 添加数据 # user = User(username='Silva72', email='@.com', password='') # db.session.add(user) # db.session.commit() # 2. 查找数据 # users = User.query.all() # for user in users: # print(user.id) # print(user.username) # print(User.query.get(2)) # print(User.query.count()) # print(User.query.filter_by(id=1)[0].email) # print(User.query.get_or_404(2)) # 3. 修改数据 user = User.query.filter_by(id=1)[0] user.username = "新名字" db.session.commit() return 'Hello World!'
删:
@app.route('/') def hello_world(): # put application's code here # 1. 添加数据 # user = User(username='Silva72', email='@.com', password='') # db.session.add(user) # db.session.commit() # 2. 查找数据 # users = User.query.all() # for user in users: # print(user.id) # print(user.username) # print(User.query.get(2)) # print(User.query.count()) # print(User.query.filter_by(id=1)[0].email) # print(User.query.get_or_404(2)) # 3. 修改数据 # user = User.query.filter_by(id=1)[0] # user.username = "新名字" # db.session.commit() # 4. 删除数据 user = User.query.filter_by(id=1)[0] db.session.delete(user) db.session.commit() return 'Hello World!'
十六、Flask_Migrate实现数据迁移
修改表类的结构后,db.create_all()不能修改,需要用数据迁移
数据迁移目的:不破坏原来数据,更改数据表的结构
| 包 | 模块 | 情况 |
|---|---|---|
| wtforms | Form | |
| flask_wtf | FlaskForm | flask对wtforms做出精简,更适合flask框架 |
| flask_sqlalchemy | SQLAlchemy | 数据库相关的 |
| flask_migrate | Alembic |
from flask import Flask, render_template, request from flask_sqlalchemy import SQLAlchemy import pymysql from flask_migrate import Migrate app = Flask(__name__) app.debug = True app.config['SECRET_KEY'] = 'spaceX' app.config['SQLALCHEMY_DATABASE_URI'] = ( 'mysql+pymysql://root:Root8834@localhost/flask_demo?charset=utf8mb4' ) app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = True db = SQLAlchemy(app) # 绑定app和数据库 migrate = Migrate(app, db) class User(db.Model): __tablename__ = 'user' id = db.Column(db.Integer, autoincrement=True, primary_key=True) username = db.Column(db.String(80), unique=True, nullable=False) email = db.Column(db.String(120), unique=True, nullable=False) gender = db.Column(db.Boolean, default=True) hobby = db.Column(db.String(120)) password = db.Column(db.String(20), nullable=False) articles = db.relationship('Article', backref='user') # 关联 def __repr__(self): return f"
is
{
self.username}" class Article(db.Model): id = db.Column(db.Integer, autoincrement=True, primary_key=True) title = db.Column(db.String(80), unique=True, nullable=False) password = db.Column(db.String(120), nullable=False) user_id = db.Column(db.Integer, db.ForeignKey('user.id')) # 定义外键 def __repr__(self): return f"
is
{
self.title}" db.create_all() if __name__ == '__main__': app.run()
Step 1:导包
Step 2:初始化一个迁移文件夹
flask db init
Step 3:当前的模型添加到迁移文件中
flask db migrate
e.g. flask db migrate -m "add password to user"
Step 4:把迁移文件中对应的数据库操作,真正的映射到数据库中
flask db upgrade
Step 5:后期改动模型后,只需反复执行step3和4即可
十七、skill
点击按钮可以激发链接
发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/175907.html原文链接:https://javaforall.net
