路由:处理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()
生成URL
url_for(函数名,参数赋值)
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()
controller是调度中心,每一个表就是一个model。例如,订单表就是订单模型,view是视图层,里面存有多个模板。
render_template(模板名称,函数赋值)
template中user.html
DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Titletitle>
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>Titletitle>
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>Titletitle>
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>Titletitle>
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 %}
注意:
- action表示提交到哪里
- 注册method不用get,因为会传到URL中,不安全
- 不会用到js,只用form.py和views.py视图函数
- submit按钮可整表提交,不需绑定按钮
template中login.html
DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>logintitle>
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()
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>logintitle>
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>
【注意】!!!!!的位置是基于十一章改变/多加的
包 | 模块 | 情况 |
---|---|---|
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>logintitle>
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>
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()
@app.route('/')
def hello_world():
# 1. 添加数据
user = User(username='Silva72', email='[email protected]', password='123456')
db.session.add(user)
db.session.commit()
return 'Hello World!'
@app.route('/')
def hello_world():
# 1. 添加数据
# user = User(username='Silva72', email='[email protected]', password='123456')
# 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='[email protected]', password='123456')
# 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='[email protected]', password='123456')
# 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!'
修改表类的结构后,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()
flask db init
flask db migrate
e.g. flask db migrate -m "add password to user"
flask db upgrade
不用js绑定按钮,用button套a标签