• flask学习笔记



    入门

    创建一个flask项目

    使用pycharm在这里插入图片描述

    • 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)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    # user.html
    <h1>Hello, {{ name }}!</h1>
    
    • 1
    • 2

    Jinja2 还支持宏。宏类似于 Python 代码中的函数。例如:

    {% macro render_comment(comment) %}
     <li>{{ comment }}li>
    {% endmacro %}
    <ul>
     {% for comment in comments %}
     {{ render_comment(comment) }}
     {% endfor %}
    ul>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    模板继承

    创建base.html

    <html>
    <head>
     {% block head %}
     <title>{% block title %}{% endblock %} - My Applicationtitle>
     {% endblock %}
    head>
    <body>
     {% block body %}
     {% endblock %}
    body>
    html>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    创建index.html

    {% extends "base.html" %}
    {% block title %}Index{% endblock %}
    {% block body %}
    {% block navbar %}
    {% endblock  %}
    {% block content %}
    {% endblock %}
    {% endblock }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    基础语法

    {{}}包裹变量
    {% %}包裹语句

    路由

    重定向

    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 %}
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    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('提交')
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    
    {{ wtf.quick_form(form) }}
    
    • 1
    • 2
    # wtf表单必须用秘钥
    app.config["SECRET_KEY"] = "hello"
    form = forms.NameForm();
    	#点击了提交按钮
        if form.validate_on_submit():
    
    • 1
    • 2
    • 3
    • 4
    • 5

    消息闪现

    
    {% with messages = get_flashed_messages() %}
      {% if messages %}
        <ul class=flashes>
        {% for message in messages %}
          <li>{{ message }}li>
        {% endfor %}
        ul>
      {% endif %}
    {% endwith %}
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    #app.py
    from flask import flash
    flash('xxxxxx')
    
    • 1
    • 2
    • 3

    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)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    在这里插入图片描述

    常用语法

    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)支持>==<

    在这里插入图片描述

    启动shell

    在Terminal终端输入

    flask shell
    
    • 1

    数据迁移

    创建 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='9@qq.com',
        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()
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25

    Blueprint

    当路由非常多的时候,可以使用蓝图管理。 Blueprint是flask内置的一个功能。

    #app.py
    from user import bp as user_page
    app.register_blueprint(user_page)
    
    • 1
    • 2
    • 3
    #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')
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    配置虚拟变量

    当一些配置比如密码、秘钥等不适合在程序里,应当从虚拟环境中配置读取。

    (venv) $ set PASSWORD=‘abcdefg’

    app.config['SECRET_KEY']=os.getenv('PASSWORD')
    
    • 1

    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
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26

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

    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
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    1. 保护路由
      对于登录才能访问的页面加上前缀@login_required即可

    自定义装饰器

    需求文件

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

    项目结构

    在这里插入图片描述

  • 相关阅读:
    【苍穹外卖 | 项目日记】第八天
    Type-C口充电器头为什么没有电压输出?
    学习Lua脚本语言
    【二十四】springboot使用EasyExcel和线程池实现多线程导入Excel数据
    Windows系统部署WebDAV服务结合内网穿透实现公网访问,轻松共享文件与资源
    点成分享 | 微流控集成系统在人体血管研究中的应用
    彻底搞懂dfs与回溯
    C生万物 | 从浅入深理解指针【最后部分】
    第9章 Apache-Dbutils实现CRUD操作
    神经网络反向传播的数学原理
  • 原文地址:https://blog.csdn.net/weixin_51277037/article/details/127436920