认识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的增删改查 
 
 
 
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=中间表名 `来进行关联 
 
 
 

           *访问和数据添加可以通过以下方式进行操作:  
 
 
 
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  
   
 
 
 

   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在哪个域名中有效,一般设置子域名,比如 
 
 
 

           *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 ` 会被模板中当成变量来渲染 
 
 
 

           *上下文处理器返回字典,在所有页面中都是可用的 
 
 
 

           *被这个装饰器修饰的钩子函数必须要返回一个字典