flask项目内默认配置Jinja库
# app.py
from flask import Flask, render_template
@app.route('/')
def index():
return render_template('index.html')
@app.route('/user/' )
def user(name):
return render_template('user.html', name=name)
# user.html
<h1>Hello, {{ name }}!</h1>
Jinja2 还支持宏。宏类似于 Python 代码中的函数。例如:
{% macro render_comment(comment) %}
<li>{{ comment }}li>
{% endmacro %}
<ul>
{% for comment in comments %}
{{ render_comment(comment) }}
{% endfor %}
ul>
创建base.html
<html>
<head>
{% block head %}
<title>{% block title %}{% endblock %} - My Applicationtitle>
{% endblock %}
head>
<body>
{% block body %}
{% endblock %}
body>
html>
创建index.html
{% extends "base.html" %}
{% block title %}Index{% endblock %}
{% block body %}
{% block navbar %}
{% endblock %}
{% block content %}
{% endblock %}
{% endblock }
{{}}包裹变量
{% %}包裹语句
redirect‘index.html’)
url_for('index')
return render_template('page_not_found.html'), 404
在flask中使用flask_bootstrap
bootstrap=flask_bootstrap.Bootstrap(app)
{% extends 'bootstrap/base.html' %}
{% block title %}{% endblock %}
{% block body %}
{% block navbar %}{% endblock %}
{% block content%}{% endblock %}
{% endblock %}
#forms.py
from flask_wtf import FlaskForm
from wtforms import StringField, SubmitField, validators, PasswordField,EmailField
from wtforms.validators import data_required, Email, Regexp
class NameForm(FlaskForm):
name = StringField("请输入你的姓名: ",[validators.Length(min=3)])
password = PasswordField('密码', [
validators.DataRequired(message="密码未输入"),
])
confirm = PasswordField('确认密码',[validators.EqualTo('password', message='两次密码不一致')])
# email = EmailField("邮箱", [validators.Email(message="邮箱格式不正确")])
email = StringField("邮箱",[validators.Regexp(r'/^.*\.com$/',message="邮箱格式不正确")])
submit = SubmitField('提交')
{{ wtf.quick_form(form) }}
# wtf表单必须用秘钥
app.config["SECRET_KEY"] = "hello"
form = forms.NameForm();
#点击了提交按钮
if form.validate_on_submit():
{% with messages = get_flashed_messages() %}
{% if messages %}
<ul class=flashes>
{% for message in messages %}
<li>{{ message }}li>
{% endfor %}
ul>
{% endif %}
{% endwith %}
#app.py
from flask import flash
flash('xxxxxx')
#config.py
basedir = os.path.abspath(os.path.dirname(__file__))
app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] =\
'sqlite:///' + os.path.join(basedir, 'data.sqlite')
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
db = SQLAlchemy(app)
db.create_all()
将寻找所有db.Model 的子类,然后在数据库中创建对应的表db.drop_all()
删除所有表数据 db.session.add()
参数是一个class(db.Model)的对象 增加或修改db.session.commit()
提交到数据库 db.session.delete()
删除 Role.query.all()
查询 Role.query.filter_by(role=user_role)
有限制条件的查询,只支持= Role.query.filter(Role.name==user_role.name)
支持>==<在Terminal终端输入
flask shell
创建 migrations迁移目录
(venv) $ flask db init
创建迁移脚本
(venv) $ flask db migrate -m "initial migration"
更新迁移脚本(当数据表模型发生改变后)
(venv) $ flask db upgrade
#app.py
from flask import Flask
from flask_mail import Message,Mail
app = Flask(__name__)
app.config.update(
MAIL_SERVER='smtp.qq.com',
MAIL_USE_SSL=True,
# 25/465 普通/加密
MAIL_PORT=465,
MAIL_USERNAME='[email protected]',
MAIL_PASSWORD='在qq邮箱获取验证码',
)
mail = Mail(app)
def send_email(to, subject, template, **kwargs):
msg = Message(subject,
sender=app.config['MAIL_USERNAME'], recipients=[to])
# msg.body = render_template(template + '.txt', **kwargs)
msg.html = render_template(template + '.html', **kwargs)
mail.send(msg)
if __name__ == '__main__':
app.run()
当路由非常多的时候,可以使用蓝图管理。 Blueprint是flask内置的一个功能。
#app.py
from user import bp as user_page
app.register_blueprint(user_page)
#user.py
from flask import Blueprint, render_template, request, flash
bp = Blueprint('user', __name__, url_prefix='/user')
@bp.route('/', methods=['GET', 'POST'])
def index():
print(request)
if request.method == 'POST':
flash('添加成功')
return render_template("user.html")
@bp.route('/add')
def add():
return render_template('add.html')
当一些配置比如密码、秘钥等不适合在程序里,应当从虚拟环境中配置读取。
(venv) $ set PASSWORD=‘abcdefg’
app.config['SECRET_KEY']=os.getenv('PASSWORD')
#models.py
from flask_login import UserMin
#UserMin自动注入is_authenticated()、is_active()、is_anonymous()、get_id()方法
from . import login_manager
class User(UserMin,db.Model):
__tablename__ = 'users'
id = db.Column(db.Integer, primary_key = True)
username = db.Column(db.String(128),index=True)
password_hash = db.Column(db.String(128)) #填写属性时仍然用password
#密码为只写属性,不可读
@property
def password(self):
raise AttributeError('password is not a readable attribute')
#设置密码
@password.setter
def password(self, password):
self.password_hash = generate_password_hash(password)
#验证密码
def verify_password(self, password):
return check_password_hash(self.password_hash, password)
@login_manager.user_loader
def load_user(user_id):
return User.query.get(int(user_id))
密码生成散列值后就无法还原成原来的密码了,所以无法读取原来的密码,只能通过比较两个密码的散列值判断相同。
#app.py
from flask_login import LoginManager
login_manager = LoginManager()
# 指未登录时,访问有权限的页面时自动跳转到的(登录)页面
login_manager.login_view = '/login'
login_manager.init_app(app)
@app.route('/login', methods=['GET', 'POST'])
def login():
db.create_all()
form = LoginForm()
if form.validate_on_submit():
# 查询用户是否存在
user = User.query.filter(User.email==form.email.data).first()
# 如果用户存在切密码正确,则登录成功
if user is not None and user.verify_password(form.password.data):
login_user(user, form.remember_me.data)
session['email']=form.email.data
redirect(url_for('index'))
return redirect(url_for('index'))
# 登录失败
flash("用户或密码不正确")
return render_template('login.html',form=form)
@app.route('/logout')
@login_required
def logout():
logout_user()
session.pop('email')
flash('You have been logged out.')
return redirect(url_for('index'))
加上前缀@login_required即可
pip freeze >requirements.txt
pip install -r requirements.txt