Flask基本使用

5.Flask基本使用

5.1 虚拟环境的创建
1.创建flask的虚拟环境
    mkvirtualenv --python=/usr/bin/python3 flask200x  
2.查看虚拟环境
    pip freeze
    pip list
3.虚拟环境迁移
    pip freeze > requirements.txt
        迁出
    pip install -r requirements.txt
        迁入
5.2 Flask项目的创建
1.安装
    国外源  pip install flask
    国内源  pip install flask -i https://pypi.douban.com/simple
2.创建项目
    代码结构
        from flask import Flask
         app = Flask(__name__)

        @app.route("/")
        def index():
            return "Hello"
        app.run()
3.启动服务器  python  文件名字.py
    默认端口号  5000  只允许本机连接
5.3 启动服务器参数修改
run方法中添加参数
    在启动的时候可以添加参数  在run()中
    debug
        是否开启调试模式,开启后修改过python代码自动重启
        如果修改的是html/js/css 那么不会自动重启
    host
        主机,默认是127.0.0.1 指定为0.0.0.0代表本机ip
    port
        指定服务器端口号
    threaded
        是否开启多线程

6. flask-script-(命令行参数)

    1.安装
        pip install flask-script
        作用
            启动命令行参数
    2.初始化
        修改  文件.py为manager.py
        manager = Manager(app=app)
        修改 文件.run()为manager.run()
    3.运行
        python manager.py runserver -p xxx -h xxxx -d -r
          参数
          - p  端口 port
          - h  主机  host
          - d  调试模式  debug
          - r  重启(重新加载) reload(restart)

7. 视图函数返回值

    (1)index返回字符串
        @app.route('/index/')
         def index():
            return 'index'
    (2)模板first.html
        @app.route('/first/')
         def hello():
            return render_template("test.html")
      静态文件css
           注意
           

6. Flask基础结构

App
    templates
        模板
    static
        静态资源
    views
        视图函数
    models
        模型
    坑点
        执行过程中manager.py和其他的文件的路径问题
    第二个坑--封装__init__文件--

7. flask-blueprint-(蓝图)

蓝图
    1. 宏伟蓝图(宏观规划)
    2. 蓝图也是一种规划,主要用来规划urls(路由)
    3. 蓝图基本使用
    - 安装
     - pip install flask-blueprint
     - 在视图文件中  初始化蓝图   blue = Blueprint('first',__name__)      
       注意导包 from flask import Blueprint
     - 在manager中   调用蓝图进行路由注册  app.register_blueprint(blueprint=blue)

8. Flask路由参数

8.1 概念
路由中带参数的请求,从客户端或者浏览器发过来的请求带参数。
基本使用:
 @blue.route('/getstudents//')
          def getstudents(id):
              return '学生%s'+id
8.2 基础语法
基础语法
    
    书写的converter可以省略,默认类型就是string
converter
    (1)string
         接收的时候也是str, 匹配到 / 的时候是匹配结束
         @blue.route('/getperson//')
         def getperson(name):
              print(name)
              print(type(name))
              return name
    (2)path
          接收的时候也是str, / 只会当作字符串中的一个字符处理
          @blue.route('/getperson1//')
          def getperson1(name):
              print(name)
              print(type(name))
              return name
    (3)int
           @blue.route('/makemoney//')
           def makemoney(money):
              print(type(money))
              return '1'
    (4)float
           @blue.route('/makemoneyfloat//')
           def makemoney(money):
              print(type(money))
              return '1'
            
    (5)uuid(uuid 类型,一种格式)
         @blue.route(('/getuu/'))
         def getuu():
              uu = uuid.uuid4()
              print(uu)
              return str(uu)
          ------------------------------------
         @blue.route('/getuuid//')
         def getuuid(uuid):
              print(uuid)
              print(type(uuid))
              return '2'
    (6)any(已提供选项的任意一个 而不能写参数外的内容  注意的是/)
         @blue.route('/getany//')
          def getany(p):
              return '1'

9.postman

请求方式
    postman
        模拟请求工具
            方法参数中添加methods=['GET','POST']
    1. 默认支持GET,HEAD,OPTIONS
    2. 如果想支持某一请求方式,需要自己手动指定
    3. 在route方法中,使用methods=["GET","POST","PUT","DELETE"]

10.反向解析

(1)概念:
        获取请求资源路径
(2)语法格式:
        url_for(蓝图的名字.方法名字)
(3)使用:
         @blue.route("/hehe/", methods=["GET","POST","PUT"])
          def hehe():
              return "呵呵哒"

          @blue.route("/gethehe/")
          def get_hehe():
              p = url_for("first.hehe")
          return p

作业:

1.执行请求login,跳转到login.html,该页面中有一个文本框,在文本框中输入红浪漫晶哥,然后点击提交,跳转到weilcome.html,该页面中显示欢迎光临尊敬的vip中p晶哥,光临红浪漫,男宾一位,拖鞋手牌拿好,楼上二楼左转。

Day02

学习目标

  • request
  • response
  • 异常
  • 会话
    • cookie
    • session
  • 模板
  • 模型

学习课程

1.request

(1)request是一个内置对象
    内置对象:不需要创建就可以直接使用的对象
(2)属性
    1.method      (请求方法)            **
    2.base_url    (去掉get参数的url) 
    3.host_url    (只有主机和端口号的url)    
    4.url         (完整的请求地址)       **
    5.remote_addr (请求的客户端地址)     **
    6.request.args.get('name')
      args  **
           - args
           - get请求参数的包装,args是一个ImmutableMultiDict对象,类字典结构对象
           - 数据存储也是key-value
           - 外层是大列表,列表中的元素是元组,元组中左边是key,右边是value
           - ImmutableMultiDict([('age', '18'), ('age', '19'), ('name', 'zs')])
           
           注意: 一般情况下  get请求方式都是在浏览器的地址栏上显示
                 eg:http://www.baiduc.com/s?name=zs&age=18
                 获取get请求方式的参数的方式:request.args.get('name')
          
     7.request.form.get('name')
       form   **
           - form
           - 存储结构和args一致
           - 默认是接收post参数
           - 还可以接收 PUT,PATCH参数
           注意:eg:
                    
获取post请求方式的参数的方式 8.files (文件上传) ** 9.headers (请求头) 10.path (路由中的路径) ** 11.cookies (请求中的cookie) 12.session (与request类似 也是一个内置对象 可以直接打印 print(session))

2 Response

    (1)返回字符串
        如果只有字符串,就是返回内容,数据
        还有第二个返回,放的是状态码
        @blue.route('/response/')
        def get_response():
               return '德玛西亚',404
    (2)render_template
        渲染模板
        将模板变成字符串
        @blue.route('/rendertemplate/')
         def render_temp():
              resp = render_template('Response.html')
              print(resp)
              print(type(resp))
              return rese,500
    (3)make_response
        Response对象
        返回内容
        状态码
        @blue.route('/makeresponse/')
        def  make_resp():
              resp = make_response('

xxxxxxxx

',502) print(resp) print(type(resp)) return rese (4)redirect 重定向 @blue.route('/redirect/') def make_redir(): return redirect('/makeresponse/') 反向解析 url_for @blue.route('/redirect/') def make_redir(): return redirect(url_for('first.make_resp')) (5)Response() @blue.route('/testresponse4/') def testresponse4(): res = Response('呵呵') print(type(res)) return res

3.异常

abort
    直接抛出 显示错误状态码  终止程序运行
    abort(404)
    eg:
        @blue.route('/makeabort/')
         def make_abort():
              abort(404)
              return '天还行'
捕获
    @blue.errorhandler()
        - 异常捕获
        - 可以根据状态或 Exception进行捕获
        - 函数中要包含一个参数,参数用来接收异常信息
    eg:
    @blue.errorhandler(502)
    def handler502(exception):
        return '不能让你看到状态码'

4.会话技术

1.请求过程Request开始,到Response结束
2.连接都是短连接
3.延长交互的生命周期
4.将关键数据记录下来
5.Cookie是保存在浏览器端/客户端的状态管理技术
6.Session是服务器端的状态管理技术
(1)cookie
Cookie
    1.客户端会话技术
    2.所有数据存储在客户端
    3.以key-value进行数据存储层
    4.服务器不做任何存储
    5.特性
        (1)支持过期时间
            max_age  毫秒
            expries  具体日期
        (2)根据域名进行cookie存储
        (3)不能跨网站(域名)
        (4)不能跨浏览器
        (5)自动携带本网站的所有cookie
    6.cookie是服务器操作客户端的数据
    7.通过Response进行操作
cookie登陆使用
    设置cookie     response.set_cookie('username',username)
        
    获取cookie     username = request.cookies.get('username','游客')
        
    删除cookie     response.delete_cookie('username')
        
(2)session
Session
    1.服务端会话技术
    2.所有数据存储在服务器中
    3.默认存在服务器的内存中
        - django默认做了数据持久化(存在了数据库中)
    4.存储结构也是key-value形势,键值对
    【注】单纯的使用session是会报错的,需要使用在__init__方法中配置app.config['SECRET_KEY']=‘110’
session登陆使用
    设置    session['username'] = username
    获取    session.get('username')
    删除
           resp.delete_cookie('session')
           session.pop('username')
(3)cookie和session总结
(1)cookie: 客户端浏览器的缓存;session: 服务端服务器的缓存
(2)cookie不是很安全,别人可以分析存放在本地的cookie并进行cookie欺骗,考虑到安全应当使用session
(3)session会在一定时间内保存在服务器上。当访问增多,会比较占用你服务器的性能,考虑到减轻服务器性能方面,应当使用cookie
可以考虑将登陆信息等重要信息存放为session,其他信息如果需要保留,可以放在cookie中
(4)session持久化问题
  • 持久化简介

    1.django中对session做了持久化,存储在数据库中
    2.flask中没有对默认session进行任何处理
        - flask-session 可以实现session的数据持久化
        - 可以持久化到各种位置,更推荐使用redis
        - 缓存在磁盘上的时候,管理磁盘文件使用lru, 最近最少使用原则
    
  • 持久化实现方案

    1.pip install flask-session
            在国内源安装
            pip install flask-sessin -i https://pipy.douban.com/simple
    2.初始化Session对象 
            (1)持久化的位置
                配置init中app.config['SESSION_TYPE'] = 'redis'
                
            (2)初始化
                创建session的对象有2种方式 分别是以下两种
                1 Session(app=app)
                2 se = Session()   se.init_app(app = app)
                
            (3)安装redis   
                pip install redis
                设置了默认开机启动,如果没有设置,那么需要将redis服务开启
                
             (4)需要配置SECRET_KEY='110'
                注意:flask把session的key存储在客户端的cookie中,通过这个key可以从flask的内存中获取                     用户的session信息,出于安全性考虑,使用secret_key进行加密处理。所以需要先设置secret_key的值。
                
            (5)其他配置--视情况而定
                app.config['SESSION_KEY_PREFIX']='flask'
        
     特殊说明:
            查看redis内容
                    redis-cli
                    keys *
                    get key
            session生存时间31天  
                ttl session
                    flask的session的生存时间是31天,django的session生存时间是14天

5.Template

  • 简介:
    (1)MVC中的View,MTV中的Template
    (2)主要用来做数据展示的
    (3)模板处理过程分为2个阶段
            1 加载
            2 渲染
    (4)jinja2模板引擎
            1.本质上是html
            2.支持特定的模板语法
            3.flask作者开发的   一个现代化设计和友好的python模板语言  模仿的django的模板引擎
            4.优点
                    速度快,被广泛使用
                    HTML设计和后端Python分离
                    减少Python复杂度
                    非常灵活,快速和安全
                    提供了控制,继承等高级功能

  • 模板语法

    1. 基本语法

      模板语言动态生成的html
             {{ var }}  变量的接收
                 从views传递过来的数据
                 前面定义出来的数据
      
    2. 结构标签

      (1)block
              首次出现挖坑操作
              第二次出现填坑操作
              第N次出现,填坑操作,会覆盖前面填的坑
              不想被覆盖,需要添加 {{ super() }}
      (2)extends
             继承
      (3)include
             包含,将一个指定的模板包含进来
      
    3. 宏定义(macro)

      (1)无参
             {% macro say()%}
                     你饿了吗???
             {% endmacro %}
             
      (2)有参
             {% macro createUser(name,age)%}
                         欢迎{{ name }} 心理没点数吗 你都{{ age }}大了
             {% endmacro %}
             
      (3)外文件中的宏定义调用需要导入也可以include
             {% macro getUser(name)%}
                     欢迎光临红浪漫{{ name }},拖鞋手牌拿好,楼上2楼左转,男宾一位
             {% endmacro %}
             
             {% from ‘html文件’ import yyy %}
             {{ getUser('action') }}
      
    4. 循环控制

      for
             for .. in 
                 loop  循环信息
                       索引  index
                       第一个   first
                       最后一个last
      if
             if 
             else
             elif
      
    5. 过滤器

      语法格式:{{ var|xxx|yyy|zzz }}
      没有数量限制
             lower
             upper
             trim
             reverse
             striptags   渲染之前将值中的标签去掉
             safe        标签生效
             eg:
                 {% for c in config %}
                          
    6. {{ loop.index0 }}:{{ loop.index}}:{{ c|lower|reverse }}
    7. {% endfor %}

6.models

  • 简介
1.数据交互的封装
2.Flask默认并没有提供任何数据库操作的API
    Flask中可以自己的选择数据,用原生语句实现功能
        原生SQL缺点:
              (1)代码利用率低,条件复杂代码语句越过长,有很多相似语句
              (2)一些SQL是在业务逻辑中拼出来的,修改需要了解业务逻辑
              直接写SQL容易忽视SQL问题
    也可以选择ORM
        SQLAlchemy
        MongoEngine
        将对象的操作转换为原生SQL
        优点
             (1)易用性,可以有效减少重复SQL
              (2)性能损耗少
              (3)设计灵活,可以轻松实现复杂查询
              (4)移植性好
3.Flask中并没有提供默认ORM
    ORM 对象关系映射
    通过操作对象,实现对数据的操作
  • sqlalchemy
flask-sqlalchemy
     使用步骤:1.pip install flask-sqlalchemy
              2.创建SQLALCHEMY对象
                                   ①:db=SQLAlchemy(app=app)
                                   ②:db=SQLAlchemy()  上面这句话一般会放到models中  因为需要db来调                                       用属性 db.init_app(app=app)
              3.config中配置  SQLALCHEMY_DATABASE_URI
                                    数据库 + 驱动 :// 用户:密码@ 主机:端口/数据库
                                    dialect+driver://username:password@host:port/database
                                    eg:mysql+pymysql://root:1234@localhost:3306/flask1905
              4.执行
                    views中db.create_all()
                    
              注意:有坑
                            (1)primary-key
                                添加主键
                            (2)SQLALCHEMY_TRACK_MODIFICATIONS
                                    app.config[‘SQLALCHEMY_TRACK_MODIFICATIONS’]=False         
使用:
    (1)定义模型
            继承Sqlalchemy对象中的model
            eg:
                class User(db.Model):
                        id = db.Column(db.Integer,primary_key=True,autoincrement=True)l
                        name = db.Column(db.String(32))
                        age = db.Column(db.Integer)
     (2)创建
            db.create_all()
     (3)删除
            db.drop_all()
     (4)修改表名
            __tablename__ = "Worker"
      (5)数据操作
            添加
                db.session.add(对象)
                db.session.commit()
            查询
                模型.query.all()

Models

学习目标

  • ORM

  • flask-migrate

  • DML

  • DQL

  • 数据定义

  • 模型关系

学习课程

1. ORM

1.1 简介
对象关系映射(Object Relational Mapping,简称ORM。ORM是通过使用描述对象和数据库之间映射,将程序中的对象自动持久化到关系数据库中。让我们从O/R开始。字母O起源于"对象"(Object),而R则来自于"关系"(Relational)。几乎所有的程序里面,都存在对象和关系数据库。在业务逻辑层和用户界面层中,我们是面向对象的。当对象信息发生变化的时候,我们需要把对象的信息保存在关系数据库中。 
当你开发一个应用程序的时候(不使用O/R Mapping),你可能会写不少数据访问层的代码,用来从数据库保存,删除,读取对象信息,等等。

[图片上传失败...(image-4f20ee-1586850584104)]

简单说,ORM 就是通过实例对象的语法,完成关系型数据库的操作的技术,是"对象-关系映射"(Object/Relational Mapping) 的缩写。

ORM 把数据库映射成对象。

[图片上传失败...(image-77ec9-1586850584104)]

2. flask-migrate(模型迁移)

使用步骤
        (1)安装
                pip install flask-migrate
        (2)初始化
                1.创建migrate对象
                  需要将app 和 db初始化 
                       migrate = Migrate()
                       migrate.init_app(app=app, db=db)
                2.懒加载初始化
                  结合flask-script使用
                  在manage上添加command (MigrateCommand)
                       manager.add_command("db", MigrateCommand)
        (3)python manager.py db xxx
                1.init     生成migrations文件夹
                2.migrate  生成迁移文件
                           不能生成有2种情况
                                (1)模型定义完成从未调用
                                (2)数据库已经有模型记录
                3.upgrade  升级  执行迁移文件
                4.downgrade 降级
          扩展:
                创建用户文件
                    python manager.py db migrate  --message ‘创建用户’

3. DML

3.1 增 删 改
1.增
    创建对象
        (1)添加一个对象
                  db.session.add()
                         eg:
                         @blue.route("/addperson/")
                          def add_person():
                              p = Person()
                              p.p_name = "小明"
                              p.p_age = 15
                              db.session.add(p)
                              db.session.commit()
                              return "添加成功"
         (2)添加多个对象
                  db.session.add_all()
                          eg:
                          @blue.route("/addpersons/")
                          def app_persons():
                              persons = []
                              for i in range(5):
                                  p = Person()
                                  p.p_name = "猴子请来的救兵%d" % random.randrange(100)
                                  p.p_age = random.randrange(70)
                                  persons.append(p)
                              db.session.add_all(persons)
                              db.session.commit()
                              return "添加成功"
2.删除
    db.session.delete(对象)
        基于查询
3.修改
    db.session.add(对象)
        基于查询
3.2 查
1.获取单个数据
    (1)get
            主键值
            获取不到不会抛错
            person = Person.query.get(3)
            db.session.delete(person)
            db.session.commit()
    (2)first
           person = Person.query.first()
2.获取结果集
    (1)xxx.query.all
            persons = Person.query.all()
    (2)xxx.query.filter_by
            persons = Person.query.filter_by(p_age=15)
    (3)xxx.query.filter
            persons = Person.query.filter(Person.p_age < 18)
            persons = Person.query.filter(Person.p_age.__le__(15))
            persons = Person.query.filter(Person.p_name.startswith("小"))
            persons = Person.query.filter(Person.p_name.endswith("1"))
            persons = Person.query.filter(Person.p_name.contains("1"))
            persons = Person.query.filter(Person.p_age.in_([15, 11]))
3.数据筛选
    (1)order_by
            persons = Person.query.order_by("-p_age")
    (2)limit
            persons = Person.query.limit(5)
    (3)offset
            persons = Person.query.offset(5).order_by("-id")
    (4)offset和limit不区分顺序,offset先生效
            persons = Person.query.order_by("-id").limit(5).offset(5)
            persons = Person.query.order_by("-id").limit(5)
            persons = Person.query.order_by("-id").offset(17).limit(5)
    (5)order_by 需要先调用执行
            persons = Person.query.order_by("-id").offset(17).limit(5)
4.pagination
    (1)简介:分页器
              需要想要的页码
              每一页显示多少数据
    (2)原生:
             persons = Person.query.offset((page_num - 1) * page_per).limit(page_per)
    (3)封装:
             参数(page,page_per,False(是否抛异常)
             persons = Person.query.paginate(page_num, page_per, False).items
5.逻辑运算
    (1)与
            and_     filter(and_(条件))
            huochelist = kaihuoche.query.filter(and_(kaihuoche.id == 1,kaihuoche.name == 'lc'))

    (2)或
            or_          filter(or_(条件))
            huochelist = kaihuoche.query.filter(or_(kaihuoche.id == 1,kaihuoche.name =='lc'))

    (3)非
            not_         filter(not_(条件))  注意条件只能有一个
            huochelist = kaihuoche.query.filter(not_(kaihuoche.id == 1))

    (4)in
            huochelist = kaihuoche.query.filter(kaihuoche.id.in_([1,2,4]))

4. 数据定义

    (1)字段类型
                Integer
                String
                Date
                Boolean
    (2)约束
        primary_key   (主键)              
        autoincrement (主键自增长)               
        unique        (唯一)          
        default       (默认)              
        index         (索引)              
        not null     (非空)           
        ForeignKey    (外键)                       
                        用来约束级联数据
                        db.Column( db.Integer, db.ForeignKey(xxx.id) )
                        使用relationship实现级联数据获取
                            声明级联数据
                            backref="表名"
                            lazy=True

5. 模型关系

5.1 一对多
(1)模型定义
          class Parent(db.Model):
              id=db.Column(db.Integer,primary_key=True,autoincrement=True)
              name=db.Column(db.String(30),unique=True)
              children=db.relationship("Child",backref="parent",lazy=True)
              def __init__(self):
                  name=self.name

          class Child(db.Model):
              id = db.Column(db.Integer, primary_key=True)
              name = db.Column(db.String(30), unique=True)
              parent_id = db.Column(db.Integer, db.ForeignKey('parent.id'))
              def __init__(self):
                  name = self.name
 (2)参数介绍:
         1.relationship函数
                    sqlalchemy对关系之间提供的一种便利的调用方式,关联不同的表;
          2.backref参数
                    对关系提供反向引用的声明,在Address类上声明新属性的简单方法,之后可以在my_address.person来获取这个地址的person;
          3.lazy参数
                    (1)'select'(默认值)
                        SQLAlchemy 会在使用一个标准 select 语句时一次性加载数据;
                    (2)'joined'
                        让 SQLAlchemy 当父级使用 JOIN 语句是,在相同的查询中加载关系;
                    (3)'subquery'
                        类似 'joined' ,但是 SQLAlchemy 会使用子查询;
                    (4)'dynamic':
                        SQLAlchemy 会返回一个查询对象,在加载这些条目时才进行加载数据,大批量数据查询处理时推荐使用。
          4.ForeignKey参数
                    代表一种关联字段,将两张表进行关联的方式,表示一个person的外键,设定上必须要能在父表中找到对应的id值
(3)模型的应用
            添加
                eg:@blue.route('/add/')
                    def add():
                        p = Parent()
                        p.name = '张三'
                        c = Child()
                        c.name = '张四'
                        c1 = Child()
                        c1.name = '王五'
                        p.children = [c,c1]

                        db.session.add(p)
                        db.session.commit()

                        return 'add success'
            查
                  eg:
                  主查从 --》 Parent--》Child
                  @blue.route('/getChild/')
                  def getChild():
                      clist = Child.query.filter(Parent.id == 1)
                      for c in clist:
                          print(c.name)
                      return 'welcome to red remonce'
                  从查主
                  @blue.route('/getParent/')
                  def getParent():
                      p = Parent.query.filter(Child.id == 2)
                      print(type(p))
                      print(p[0].name)
                      return '开洗'
52 一对一
   一对一需要设置relationship中的uselist=Flase,其他数据库操作一样。
5.3 多对多
(1)模型定义
          class User(db.Model):
              id = db.Column(db.Integer,primary_key=True,autoincrement=True)
              name = db.Column(db.String(32))
              age = db.Column(db.Integer,default=18)

          class Movie(db.Model):
              id = db.Column(db.Integer,primary_key=True,autoincrement=True)
              name = db.Column(db.String(32))

          class Collection(db.Model):
              id = db.Column(db.Integer,primary_key=True,autoincrement=True)
              u_id = db.Column(db.Integer,db.ForeignKey(User.id))
              m_id = db.Column(db.Integer,db.ForeignKey(Movie.id))
(2)应用场景
          购物车添加
              @blue.route('/getcollection/')
              def getcollection():
                    u_id = int(request.args.get('u_id'))
                    m_id = int(request.args.get('m_id'))
                    c = Collection.query.filter(Collection.u_id == u_id).filter_by(m_id = m_id)

                    if c.count() > 0:
                        print(c.first().u_id,c.first().m_id)
                        # print(c)
                        # print(type(c))
                        # print('i am if')
                        return '已经添加到了购物车中'
                    else:
                        c1 = Collection()
                        c1.u_id = u_id
                        c1.m_id = m_id
                        db.session.add(c1)
                        db.session.commit()
                        return 'ok'

你可能感兴趣的:(Flask基本使用)