浅学Flask

10 min

1.debug模式

如果你的 PyCharm 是中文版,那么你可以参考以下步骤操作

  • 在 PyCharm 的主菜单中,点击 运行 | 编辑配置 。
  • 在 运行/调试配置 对话框中,选择 Flask Server 类型的配置 。
  • 在 Flask Server 配置对话框中,勾选 FLASK_DEBUG 复选框 。这样,每次你保存代码更改时,PyCharm 就会自动重启运行中的应用。
  • 好处

    • 不需要手动重启服务器

    • 如果出现bug,可以在浏览器中直接调试

      # 从flask包中导入flask类
      from flask import Flask
      
      # 定义类的对象 app。
      # __name__表示当前在app.py这个模块;作用是如果出现bug可以快速定位;以及如果寻找一个模板文件,有一个相对路径。
      app = Flask(__name__)
      
      # 创建一个路由,('/')表示根路由
      @app.route('/')
      def hello_world():  # put application's code here
          return 'rtyl'
      
      # 表示如果这个模块当作主入口文件运行,就运行一下代码。
      if __name__ == '__main__':
          app.run()

1.1 修改host

  • 作用:让同一个局域网内其他电脑访问我的项目
  • 怎么做
    • 选择运行|调试配置(在绿色运行符号的左边)
    • 点击编辑配置
    • 在其他选项中写:--host=0.0.0.0
    • 选择ok

1.2 修改端口号

如果5000端口被占用,就需要修改到其他端口

怎么做

  • 选择运行|调试配置(在绿色运行符号的左边)
  • 点击编辑配置
  • 在其他选项中写:--host=0.0.0.0后加一个”空格“写入 --port=8000
    • --host=0.0.0.0 --port=8000
    • 让端口号由5000变为8000

2. url与视图的映射

  • 三种方式
from flask import Flask, request

app = Flask(__name__)


@app.route('/')
def hello_world():  # put application's code here
    return 'Hello World!'

# 1.定义无参数url
@app.route('/index')
def index():
    return '你好中国'

# 2.带参数的url:将参数固定到path中
# <参数>:参数放尖括号里面
# % blog_id是一个占位符,表示将blog_id的值插入到字符串中。
@app.route("/blog/passage <int:blog_id>")
def blog_detail(blog_id):
    return "您访问的博客是:%s" % blog_id

# 3.查寻url的方式传参
# args:arguments(参数)
# request.args类字典类型
# f表示寻找{变量}
# book/passage?page=2
@app.route('/book/passage')
def passage_page():
    page = request.args.get('page', default=1, type=int)
    return f"获取的是第{page}的图书页数"

if __name__ == '__main__':
    app.run()

3. 模板渲染(跳过)

  • 引入 from flask import Flask, render_template,

    • rander_template
  • from flask import Flask, render_template
    
    app = Flask(__name__)
      @app.route('/')
      def hello_world():  
          return render_template("index.html") #这个html是在template里的,这个函数起到渲染这个html文件的作用
    
      if __name__ == '__main__':
          app.run()

4. Flask连接SQL数据库

4.1 Navicat Premium 15

  • 它是数据库的管理工具,包括MySQL、MariaDB、MongoDB、Oracle、PostgreSQL和SQLite等。

  • 支持可视化操控数据库

  • pymysql是Python编程语言下的一个用于连接MySQL的库

4.2 SQLALchemy

  • SQLAlchemy是Python编程语言下的一款ORM框架

    • ORM是Object-Relational Mapping的缩写,即对象关系映射。

5. ORM模型与表的映射

  • 一个orm模型和数据库中的一个表相对应

  • orm技术提供了面向对象和sql交互的桥梁

    • class User(db.Model):
          __tablename__ = "user"
          id = db.Column(db.Integer, primary_key = True, autoincrement = True)
          username = db.Column(db.String(100), nullable= False)
          password = db.Column(db.String(100), nullable=False)
      

6. ORM模型的CRUD操作

  • 增加(Create)
@app.route("/user/add")
def add_user():
    # 1.创建ORM对象
    user = User(username="张三",password="123456")
    # 2.将ORM对象添加到db.session中
    db.session.add(user)
    # 3.将db.session中的改变同步到数据库中
    db.session.commit()
    return "用户创建成功!"
  • 读取(Read)
@app.route("/user/query")
def query_user():
    user = User.query.get(1)
    print(f"{user.id}:{user.username}-{user.password}")
    return "数据查询成功!"
  • 更新(Update)
@app.route("/user/update")
def update_user():
    user = User.query.get(1)
    user.password = "2222222"
    db.session.commit()
    return "数据修改成功!"
  • 删除(Delete)
@app.route("/user/delete")
def delete_user():
    user = User.query.get(1)
    db.session.delete(user)
    db.session.commit()
    return "数据删除成功!"

7. ORM模型外键与表的关系

  • 在Mysql中,外键可以让表之间关系变得更加紧密, 在SQlAlchemy中, 通过ForeignKey类来实现,并且可以指定表的外键约束

author_id = db.Column(db.Integer, db.ForeignKey("user.id"))

  • author = db.relationship("User", backref="articles")表示将User表和articles表互相关联(只要写一个就可以互相关联)
  • author = db.relationship("User", back_populates= "articles")
    
    atticles = db.relationship("User", back_populates= "author")
    
    # 两行代码对应两个位置都要写,这样才可以互相关联

8. flask-migrate 迁移ORM模型

  • 安装“flask-migrate`

  • from flask-migrate import Migrate写在开头

  • 在终端三部曲

    • flask db init # 只要写一次
      flask db migrate # 之后如果修改了表格,只要输入后两项
      flask db upgrade

9. jinja2

渲染模板

  • @app.route("/blog/<blog_id>")
    def blog_detail(blog_id):
        return render_template("blog_detail.html", blog_id = blog_id, username = "你好")
  • {{name}}表示传入了一个动态参数,在return函数的时候传入相应的参数就可
  • 在template里面就放html文件,文件名字就是blog_detail.html

模板返回对象属性

  • 对于传入的参数中有多个属性的情况下,可以用 .来选你要显示的属性

10. 实战

10.1 问答平台项目实战搭建

项目架构

  1. 创建 config.py文件

    1. 比如一些配置内容要写在里面

    2. 与app.py进行绑定

      1. import config
        app.comfig.from_object(config)#绑定配置信息
  2. 创建 exts.py文件(拓展文件)

    1. 作用

      1. 这个文件存在的意义是为了解决循环引用的问题
    2. 在exts中写:

      1. from flask_sqalalchemy import SQLAlchemy
        
        db = SQLAlchemy()
    3. flask.1

    4. 创建了db对象,现在进行和app绑定

      1. 在app中写

        1. from exts import db
          
          db.init_app(app)

          实行了先创建,再绑定再作用

  3. 创建 models.py文件

  4. 创建 blueprints python包(蓝图)

    1. 作用:

      1. 将视图函数模块化,分类方便后期管理
      2. 比如可以放一个授权区和一个问答区,就可以这样写:
        1. auth.py
        2. qa.py
    2. 在auth中可以写

      1. from flask import Blueprint
        
        bp = Blueprint("auth", __name__, url_prefix="/auth")# 名字,固定写法,url前缀
        
        @bp.route("/login")
        def login():
            ddfjssdfodfp.
    3. 在qa中可以这样写

      1. from flask import Blueprint
        
        bp = Blueprint("qa", __name__, url_prefix="/") # 只写一个斜杆,表示根路径
        
        @bp.route("/")
        def index:
            pass
    4. 与app进行绑定

      1. from blueprints.qa import bp as qa_bp
        from blueprints.auth import bp as auth_bp #取个别名,避免重复
        
        app.register_blueprint(qa_bp)
        app.register_blueprint(auth_bp)# 注册蓝图

10.2 User模型创建

  • 在models文件中
from exts import db
from datetime import datetime


class UserModel(db.Model):
    __tablename__ = "user"
    id = db.Column(db.Integer, primary_key=True, autoincrement=True)
    username = db.Column(db.String(100), nullable=False)
    password = db.Column(db.String(100), nullable=False, unique=True)
    join_time = db.Column(db.DateTime, default=datetime.now)
  • 在app文件中

    from models import UserModel #导入UserModel
    from flask_migrate import Migrate #迁徙ORM模型
    
    migrate = Migrate(app, db) #赋值

10.3 注册模板渲染

  • 需求:前端提供静态页码代码,后端要把它渲染成动态页面

    • 方法1:用jinja
      • 视图函数写在auth蓝图里
      • 渲染模板要导入 render_template
      • 静态模板里的相对路径改成用url_for的方式,这样就可匹配动态页面找到对应的样式匹配成功
        • flask.2
  • 对于相同的内容,可以把相同的内容提取出来,之后写入到base.html中,然后在原文件中只要用

    • {% block 内容名 %}{% endblock %}
      
    • 这样就可以实现对于特殊内容的替换

10.4 flask发送邮箱功能实现

  1. 安装模块 pip install flask-mail

  2. 在qq邮箱中开启smtp

  3. config文件中

    # 邮箱配置
    MAIL_SERVER = "smtp.qq.com" #如果是选网易邮箱,就把qq换掉
    MAIL_USE_SSL = "True"
    MAIL_USERNAME = 465
    MAIL_PASSWORD = "开启SMTP服务时生成的授权码"
    MAIL_DEFAULT_SENDER = "邮箱账号"
    1. exts文件中

      from flask_mail import Mail
      
      mail = Mail()
    2. app文件中

      基本逻辑就是:导入+初始化 —> 之后就可以用了

      from exts inport mail
      
      mail.init_app(app)
    3. 测试一下:在 auth文件中

      from exts import mail
      
      @bp.route("/mail/test")
      def mail_test():
          message = Message(subject = "邮箱设置"recipients = [你的接收邮箱, body = "这是一条测试邮箱" ])
          mail.sent(message)
          return "邮件发送成功!

10.5 发送邮箱验证码功能实现

  1. auth文件中

    from flask import request
    import string
    import random
    
    @bp.route("/capture/email")
    def get_email_capture():
        email = request.args.get("email")# args,就是传输的意思
        source = string.digits*4 #从这个包中选随机的数字
        capture = random.sample(source, 4)
        # print(capture),发现是列表,要变成字符串
        capture = "-".join(capture) # 把每个字符串连接起来,中间是"-"
        message = Message(subject = "验证码"recipients = [你的接收邮], body = "这是一条测试邮箱" )
        mail.sent(message)
        return "success"
    1. 验证用户提交的邮箱和验证码是否对应正确

      1. 存储一下,可以放在memcached/redis(因为不是很重要的信息),这两个还是要学的。

      2. 或者用数据库存储

        1. 缺点,读取比较慢

        2. 写法:

          1. models文件中

            class EmailCaptureModel(db.Model):
                __tablename__ = "email_capture"
                id = db.Column(db.Integer, primary_key=True, autoincrement=True)
                email = db.Column(db.String(100), nullable=False)
                capture = db.Column(db.String(100), nullable=False)
            
          2. auth文件中

            from models import EmailCaptureModel, db
            
            # 写在mail下的shi'tu
            email_capture = EmailCaptureModel(email = email, capture = capture)
            db.session.add(email_capture)
            db.session.commit()
            return "success!"