Flask入门到项目实战

   认识web
        URL详解
           url是 uniform Resource Locator 的简写,统一资源定位符
        一个URL由以下几个部分组成:
            
scheme://host:port/path/?query-string=xx#anchor

  

        scheme:代表的是访问的协议,一般为http或者https以及ftp等
        host:主机名,域名,比如www.google.cn
        port:端口号。当你访问一个网站的时候,浏览器默认的使用80端口
        path:查找路径。比如www.jianshu.com/trending/now,后面的trending/now就是path
        query-string:查找字符串,比如www.baidu.com/s?wd=python,后面的wd=python就是查询字符串
        anchor:锚点,后台一般不用管,前端用来做页面的定位的
注意:URL中的所有字符都是ASSCII字符集,如果出现非ASCII字符,比如中文,浏览器会进行编码再传输
笔记:如果使用的是http协议,那么浏览器就会使用80端口去请求这个服务器的资源
           如果使用的是https协议,那么浏览器就会使用443端口去请求这个服务器的资源
 
Web服务器和应用服务器以及web应用框架
    Web服务器:负责处理http/https请求,响应静态文件,常见的有Apache,Nginx以及微软IIS
    应用服务器:负责处理逻辑的服务器。比如php,python的代码,是不能直接通过nginx这种web服务器来处理的密支那通过应用服务器来处理,常见的应用服务器有uwsgi,tomcat
Web应用框架:一般使用的某种语言,封装了常用的web功能的框架就是web应用框架,flask,Django以及Java中的SSH(Structs2+Spring3+Hibernate3)框架都是web应用框架
 
第一个flask程序讲解
    1.第一次创建项目的时候,要添加flask虚拟环境,添加虚拟环境的时候,一定要选择到python这个执行文件。比如你的flask的虚拟环境的目录在/User/Virtualenv/flask-env/bin/python
    2.flask程序代码详细解释
    #encdding:utf-8
 
    # 从flask这个框架中导入Flask这个类
    from flask import Flask
    # 初始化一个Flask对象
    # Flask()
    # 需要传递一个参数__name__
    # 1.方便flask框架去寻找资源
    # 2.方便flask插件比如Flask-Sqlalchemy出现错误的时候美好去寻找问题所在的位置
 app = Flask(__name__)

    # @app.route是一个装饰器

  # @开头,并且在函数的上面,说明是装饰器

    # 这个装饰器的作用,是做一个url与视图函数的映射
    # 127.0.0.1:5000/ -> 去请求hello_world这个函数,然后将结果返回给浏览器
 @app.route('/')
    def hello_world():
        return 'Hello World!'

 # 如果当前这个文件是作为入口程序运行,那么就执行app.run()

    if __name__ == '__main__':
        # app.run()
        # 启动一个应用服务器,来接受用户的请求
        # while True():
        #     listen()
        app.run()

设置debug模式

    1.在app.run()中传入一个关键字参数debug,app_run(debug=True),就设置当前项目为debug模式
    2.debug模式的两大功能:
        *当程序出现问题的时候,可以在页面中看到错误信息和出错的位置
        *只要修改了项目中的python文件,程序会自动加载,不需要手动重新启动程序
 
使用配置文件
    1.新建一个`config.py`文件
    2.在主app文件中导入这个文件,并且配置到`app` 中,示例代码如下:
      
```import config
    app.config.form_object(config)
    3.还有许多其他的参数,都是在这个配置文件中,比如`SECRET_KEY`,`SQLALCHEMY`这些配置,都是在这个文件中
Url传参数
    1.参数的作用:可以在相同的url,但可以指定不同的参数,来加载不同的数据
    2.在flask中如何使用参数:
        
    @app.route(‘/aritcle/<id>’)
    def aritcle(id):
        return u’您请求的参数是: %s’ % id 
    *参数需要放在两个尖括号中
    *视图函数中需要放与url同名的参数s
反转URL
    1.什么叫做反转url:从视图函数到url的转换叫做反转url
    2.反转url的用处:
        *在页面重定向的时候,会使用url反转
        *在模板中,也会使用url反转
页面跳转和重定向
    1.用处:在用户访问一些需要登录的页面的时候,如果用户没有登录,那么可以让他重定向到登录页面
    2.代码实现:
    from flask import redirect, url_for
    Redirect(url_for(‘login')
 
Flask渲染模板Jinja2模板和传参
    1.如何渲染模板
        *模板放在`templates`文件夹下
        *从`flask`中导入`render_template`函数
        *在视图函数中,使用`render_template`函数,渲染模板,注意:只需要填写模板的名字,不需要填写`templates`这个文件夹的路径
    2.模板传参
        *如果只有一个或者少量参数,直接在`render_template`函数中添加关键字参数就可以了。
        *如果有多个参数的时候,那么可以先把所有的参数放在字典中,然后再`render_template`中使用2个*,把字典转换成关键字传递进去,
         这样的代码更加方便管理和使用
    3.在模板中如果要使用一个变量,语法是:`{{ params }}`
    4.访问模型中的属性或者是字典,可以通过`{{ params.property}}`或者是使用{{ params[‘property']}}都是可以的
If判断
    1.语法
       {% if XXX %}
       {% else %}
       {% endif %} 
 
过滤器(有很多去官网)
    1.介绍和语法
        *介绍:过滤器可以处理变量,把原始的变量经过处理后再展示出来。作用的对象是变量
        *语法:
        {{ avater|default(‘xxx’)}}
    2.default过滤器:如果当前变量不存在,这个时候可以指定默认值
    3.length过滤器:求列表或者字符串或者字典或者元组的长度  
       {{ list|length }}
    4.常用的过滤器(自己百度)
      
继承和block(用于前端页面)
    1.继承作用和语法
        *作用:可以把一些公共的代码放在父模板中,避免每个模板写同样的代码
        *语法 
        {% extends ‘base.html' %}
    2.block实现
        *作用:可以让子模板实现一些自己的需求,父模板需要提前定义好
        *注意点:子模板中的代码,必须放在block块中
 
URL链接:
    使用`url_for(视图函数名称)`可以反转url
 
加载静态文件
    1.语法`url_for(’static’, filename=‘路径’)`
    2.静态文件,flask会从`static`文件夹中开始寻找,所以不需要再写`static`这个路径
    3.可以加载`css`,`js`,`Image`....所有的静态文件 
    <link rel=“stylesheet” href=“{{ url_for(’static’, filename=‘css/index.css’) }}”
    <script src=“{{ url_for(’static’, filename=‘js/index.js’) }}”
    <img src=“{{ url_for(’static’, filename=‘images/index.png')}}"
Flask-SQLAlchemy的介绍
    1.ORM: Object Relationship Mapping (模型关系映射)
    2.flask-sqlalchemy是一套ORM框架
    3.ORM的好处:可以让我们操作数据库跟操作对象是一样的,非常方便,因为一个表就抽象成一个类,一条数据就抽象成该类的一个对象。 
 
建库 create database db_demo1 charset utf8;
 
Flask-SQLAlchemy的使用
    1.初始化和设置数据库配置信息
        *使用flask_sqlalchemy中的SQLAlchemy进行初始化 
        From flask_sqlalchemy import SQLAlchemy
        app = Flask(__name__)
        db = SQLAlchemy(app)
    2.设置配置信息:在’config.py’文件中添加以下配置信息 
 #mysql+mysqldb://username:password@host:port/database
    DIALECT = 'mysql'
    DRIVER = 'mysqldb'
    USERNAME = 'root'
    PASSWORD = '123'
    HOST = '127.0.0.1'
    PORT = '3306'
    DATABASE = 'db_demo1'
    SQLALCHEMY_DATABASE_URI = "{}+{}://{}:{}@{}:{}/{}?charset=utf8  ".format(DIALECT, DRIVER, USERNAME, PASSWORD, HOST, PORT, DATABASE)
    SQLALCHEMY_TRACK_MODIFICATIONS = False

 3.在主app文件中,添加配置文件: 

 From flask_sqlalchemy import SQLAlchemy
        app = Flask(__name__)
        db = SQLAlchemy(app)

   4.做测试 

    db.create_all()
        如果没有报错,说明配置没有问题。
SQLAlchemy的增删改查
    1.增      
article1 = Article('111',2222)
        db.session.add(article1)
        db.session.commit()

 2.删 

#
# 先查后删再提交
article2 = Article.query.filter(Article.title == 'aaa').first()
db.session.delete(article2)
db.session.commit()

   3.改    

   
 #
 # 先查后改再提交
 article2 = Article.query.filter(Article.title == '111').first()
 article2.title = 'aaa'
 db.session.commit()
  

   4.查   

 #
  article2 = Article.query.filter(Article.title == 'aaa').first()
  if article2:
      print article2.title,article2.content
【**重点**】
Flask-SQLAlchemy外键及其关系
    1.外键       
#用户表
class User(db.Model):
    __tablename__ = 'user'
 
    id = db.Column(db.Integer, primary_key=True, autoincrement=True)
    username = db.Column(db.String(100), nullable=False)
 
    def __init__(self, username):
        self.username = username

#文章表

class Article(db.Model):
    __tablename__ = 'aritcle'
 
    id = db.Column(db.Integer, primary_key=True,autoincrement=True)
    title = db.Column(db.String(100), nullable=False)
    content = db.Column(db.Text, nullable=False)
    author_id = db.Column(db.Integer, db.ForeignKey('user.id'))
    # 正向引用反向引用
    author = db.relationship('User', backref=db.backref('articles'))
 
    def __init__(self, title, content, author_id):
        self.title = title
        self.content = content
        self.author_id = author_id

db.create_all()
author = db.relationship('User', backref=db.backref('articles’))
解释:
    *给`Article`这个模型添加一个`author`属性,可以访问这篇文章的作者数据,像访问普通属性一样。
    *`backref`是定义反向引用,可以通过`User.article`访问这个模型所写的所有文章
 
    2.多对多
        *多对多的关系,要通过一个中间表进行关联
        *中间表,不能 ` class ` 的方式实现,只能通过 ` db.Table ` 的方式实现。
        *设置关联:` tags = db.relationship(’Tag’, secondary=article_tag, backref=db.backref(‘articles’)) ` 需要使用一个关键字 ` secondary=中间表名 `来进行关联
        *访问和数据添加可以通过以下方式进行操作: 
    1.添加:
  article1 = Article(title='bbb')
  article2 = Article(title='ccc')
 
  tag1 = Tag(name='111')
  tag2 = Tag(name='222')
 
   article1.tags.append(tag1)
   article1.tags.append(tag2)
 
   article2.tags.append(tag1)
   article2.tags.append(tag2)
 
   db.session.add(article1)
   db.session.add(article2)
 
   db.session.add(tag1)
   db.session.add(tag2)
 
   db.session.commit()

 

    2.访问
        
article1 = Article.query.filter(Article.title == 'bbb').first()
tags = article1.tags
for tag in tags:
    print tag.name

 

Flask-Scripte的介绍与安装与使用
    1.Flask-Script:Flask-Script的作用是可以通过命令行的形式来操作Flask,例如通过命令跑一个开发版本的服务器,设置数据库,定时任务等。
    2.安装:pip install flask-script 
    3.如果直接在主 ` manage.py ` 中写命令,那么在终端就只需要 ` python manage.py  command_name ` 就可以了
    4.如果把一些命令集中在一个文件中,那么在终端就需要输入一个父命令,比如 ` python manage.py db init`
    5.案例代码 
#encoding: utf-8
 
from flask_script import Manager
 
DBManager= Manager()
 
@DBManager.command
def init():
    print "数据库初始化"
 
@DBManager.command
def migrate():
    print "数据库迁移"

 

 
#encoding: utf-8
 
from flask_script import Manager
from flask_script_demo import app
from db_scripts import DBManager
 
mananger = Manager(app)
 
mananger.add_command('db', DBManager)
 
@mananger.command
def runserver():
    print '服务器运行成功!'
 
if __name__ == '__main__':
    mananger.run()

 

分开 ` models `以及解决循环引用:
    1.分开 ` models `的目的是为了让代码更加方便管理
    2.如何解决循环引用:把 ` db `放在一个单独的文件中,切断循环引用就可以了。 
 
Flask-Migrate的介绍和使用
    1.介绍:因为 ` db.create_all ` 在后期修改字段的时候,不会自动映射到数据库,必须删除表,然后重新运行 ` db.create_all ` 才会重新映射,这样不符合实际需求,因此flask-migrate就是为了解决这个问题,它可以在每次修改的东西映射到数据库中。
    2.安装 ` pip install flask-migrate ` 
    3.使用 ` flask_migrate `必须借助 ` flask-scripts `,这个包的 ` MigrateCommand  ` 中包含了所有和数据库相关的命令
    4. ` flask_migrate ` 相关命令
        * ` python manage.py db init `: 初始化一个迁移脚本环境,只需要执行一次
        * ` python manage.py db migrate `: 将模型生成迁移文件,只要模型更改了,就需要执行一遍这个命令
        * ` python manage.py db upgrade `: 将迁移文件真正映射到数据库中,每次运行了 ` migrade `命令后,就要记得运行这个命令
 
cookie:
    1. ` cookie ` 出现的原因:在网站中,http请求是无状态的,也就是说即使第一次和服务器连接后并且登录成功后,第二次请求服务器依然不能知道当前请求的是哪个用户,cookie的出现就是为了解决这个问题,第一次登录后服务器返回一些数据(cookie)给浏览器,然后浏览器保存到本地,当该用户发送第二次请求的时候,就会自动的把上次请求存储的cookie数据自动的携带给服务器,服务器通过浏览器携带的数据就能判断当前用户是哪一个。
    2.如果服务器返回了 ` cookie `给浏览器,那么浏览器下次再请求相同的服务器的时候,就会自动的把 ` cookie ` 发送给浏览器,这个过程,用户根本不需要管。
 
session:
  1. ` session ` 介绍:session和cookie的作用有点类似,都是为了存储用户相关信息。不同的是,cookie是存储在本地浏览器,而session存储在服务器。存储在服务器的数据会更加安全,不容易被窃取。但存储在服务器也有一定的弊端,就是会占用服务器的资源,但服务器已经发展至今,保存一些session信息还是绰绰有余的
  2. 使用 ` session `的好处:**1.敏感数据不是直接发送给浏览器,而是发送一个` session_id `,服务器将 ` session_id `和敏感数据做一个映射存储在 ` session `(在服务器上面)中,更加安全。**2.` session ` 可以设置过期时间,也从另一个方面,保证了用户的账号安全
 
flask中的session工作机制
     1.介绍:把敏感数据加密后放入` session `中,然后把 ` session `存放到 ` cookie `中,下次请求的时候,再从浏览器发送过来的 ` cookie `中读取 ` session `然后再从` session `中读取敏感数据,并进行解密,获取最终用户数据。
    2.flask的这种 ` session `机制,可以节省服务器的开销,因为把所有的信息都存储到了客户端(浏览器)
    3.安全是相对的,把 ` session `放到 ` cookie `中,经过加密,也是比较安全的,这点大家可以放心使用。  
 
flask中使用cookie和session
    1.cookies:在Flask中操作cookie,是通过response对象来操作,可以在response返回之前,通过response.set_cookie来设置,这个方法有以下几个参数需要注意:
        *key:设置cookie的key
        *value:key对应的value
        *max_age:改cookie的过期时间,如果不设置,则浏览器关闭后就会自动过期
        *expires:过期时间,应该是一个datetime类型
        *domain:改cookie在哪个域名中有效,一般设置子域名,比如cms.example.com
        *path:该cookie在哪个路径下有效
 
    2.session:Flask中的session是通过from flask import session 。然后添加值key和value进去即可,并且,Flask中的session机制是将session信息加密,然后存储在cookie中,专业术语叫做 client side session
 
操作session
    1.session的操作方式:
        *使用 ` session `需要从` flask `中导入 ` session `,所有和 ` session `相关的操作都是通过这个变量
        *使用 ` session `需要设置 ` SECRET_KEY `,用来作为加密的秘钥。并且这个 ` SECRET_KEY `如果每次服务器启动后都会变化的话,那么之前的 ` session ` 就不能再通过当前这个` SECRET_KEY `进行解密了
        *操作 ` session `的时候,跟操作字典是一样的。
        *添加 ` session `:` session[‘username'] `。
        *删除 ` session.pop(‘username’) ` 或者 ` del session[‘username’] `
        *清除所有 ` session `:`session.clear() `
        *获取 ` session.get(‘XXX’) `
    2.设置session的过期时间
        *如果没有指定session的过期时间,那么默认是浏览器关闭后就自动结束
        *如果设置了session的permanent属性为True,那么过期时间是31天
        *可以通过给 ` app.config ` 设置 ` PERMANENT_SESSION_LIFETIME `来更改过期时间,这个值得数据类型是` datetime.timedelay` 类型
 
Get请求和post请求
    1.get请求
        *使用场景:如果只对服务器获取数据,并没有对服务器产生任何影响,那么这个时候使用get请求。
        *传参:get请求参数是放在url中,并且是通过 ` ? `的形式来指定key和value。
    2.post请求
        *使用场景:如果要对服务器产生影响,那么使用post请求
        *传参:post请求传参不是放在url中,是通过 ` form data `的形式发送给服务器
get和post请求获取参数
    1.get请求是通过 ` request.args `来获取
    2.post请求是通过 ` request.form `来获取
    3.post请求在模板中要注意几点:
        *input标签中,要写name来标识这个value和key,方便后台获取
        *在写form表单的时候,要指定 ` method=‘POST’ `,并且要指定 ` action=‘/login/ ` 
 4.示例代码
   
 <form action="{{ url_for('login') }}" method="post">
        <table>
            <tbody>
                <tr>
                    <td>用户名:</td>
                    <td><input type="text" name='username' placeholder="请输入用户名"></td>
                </tr>
                <tr>
                    <td>密码:</td>
                    <td><input type="text" name='password' placeholder="请输入密码"></td>
                </tr>
                <tr>
                    <td></td>
                    <td><input type="submit" placeholder="登录"></td>
                </tr>
            </tbody>
        </table>
    </form>

 

保存全局变量的g属性
        g: global
          1.g对象是专门用来保存用户的数据的
          2.g对象在一次请求中,都是可以使用的  
 
钩子函数(hook):
    1.before_request:
        *在请求之前执行
        *是在视图函数执行之前执行
        *这个函数这是一个装饰器,它可以把需要设置为钩子函数的代码放到视图函数执行之前来执行
    2.context_processor:
        *上下文处理器应该返回一个字典,字典中的 ` key ` 会被模板中当成变量来渲染
        *上下文处理器返回字典,在所有页面中都是可用的
        *被这个装饰器修饰的钩子函数必须要返回一个字典
 
posted @ 2018-04-15 13:08  木叶苍蓝  阅读(313)  评论(0编辑  收藏  举报