flask学习笔记

Flask学习目录

  • 入门
    • 创建一个flask项目
    • Jinja
      • 渲染模板
      • 模板继承
      • 基础语法
    • 路由
      • 重定向
      • url构建
      • 404
  • 基础
    • Bootstrap
      • base.html
    • WTForms
    • 消息闪现
    • SQLAlchemy
      • 配置
      • 常用语法
    • 启动shell
    • 数据迁移
    • flask-mail
    • Blueprint
    • 配置虚拟变量
    • flask-login 登录
      • 自定义装饰器
    • 需求文件
    • 项目结构

入门

创建一个flask项目

使用pycharmflask学习笔记_第1张图片

  • template 放置html页面
  • static 放置静态资源

Jinja

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构建

url_for('index')

404

return render_template('page_not_found.html'), 404

基础

Bootstrap

在flask中使用flask_bootstrap

  1. 在app.py添加bootstrap=flask_bootstrap.Bootstrap(app)
  2. 在html顶部添加{%extends ‘bootstrap/base,html’%}

base.html

{% extends 'bootstrap/base.html' %}
{% block title %}{% endblock %}
{% block body %}
{% block navbar %}{% endblock  %}
{% block content%}{% endblock  %}
{% endblock %}

WTForms

#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')

SQLAlchemy

配置

#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)

flask学习笔记_第2张图片

常用语法

  1. db.create_all() 将寻找所有db.Model 的子类,然后在数据库中创建对应的表
  2. db.drop_all() 删除所有表数据
  3. db.session.add()参数是一个class(db.Model)的对象 增加或修改
  4. db.session.commit()提交到数据库
  5. db.session.delete()删除
  6. Role.query.all()查询
  7. Role.query.filter_by(role=user_role)有限制条件的查询,只支持=
  8. Role.query.filter(Role.name==user_role.name)支持>==<

flask学习笔记_第3张图片

启动shell

在Terminal终端输入

flask shell

数据迁移

创建 migrations迁移目录
(venv) $ flask db init
创建迁移脚本
(venv) $ flask db migrate -m "initial migration"
更新迁移脚本(当数据表模型发生改变后)
(venv) $ flask db upgrade

flask-mail

#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

当路由非常多的时候,可以使用蓝图管理。 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')

flask-login 登录

  1. 修改model
#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))

密码生成散列值后就无法还原成原来的密码了,所以无法读取原来的密码,只能通过比较两个密码的散列值判断相同。

  1. 配置路由
#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'))
 
  1. 保护路由
    对于登录才能访问的页面加上前缀@login_required即可

自定义装饰器

需求文件

  1. 生成所需要的第三方库
    pip freeze >requirements.txt
  2. 下载所需要的第三方库
    pip install -r requirements.txt

项目结构

flask学习笔记_第4张图片

你可能感兴趣的:(flask,python,学习)