目录:

  一、变量引用

内容:

备注:PyCharm小技巧,comm+alt+l  自动修改格式,comm+alt+return  向上添加新行

  一、变量引用

  1、url生成

  

from flask import Flask,render_template #在Flask中使用render_template代替render使用

app = Flask('__name__')

@app.route('/') #所有的url都使用app.route做装饰器来引用
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<link rel="stylesheet" href="{{ url_for('static',filename='style.css') }}"/>
</head>
<body>
<h1>{{ title }}</h1>
<a href="{{ url_for('.services') }}">Services</a>
<a href="{{ url_for('.about') }}">About</a>
</body>
</html>

def hello_world():
return render_template('index.html', title='Hello World') @app.route('/services')
def services():
return 'Services!' if __name__ == '__main__':
app.run()

  2、增加debug

from flask import Flask

app = Flask(__name__)

@app.route('/')
def hello_world():
return '<h1>Hello World!</h1>' if __name__ == '__main__':
app.run(debug=True) #增加这个参数,可以在修改完毕后不重启直接运行

  3、配置文件

  在根目录下使用一个config.py文件,内容:

  DEBUG = True

  在主配置文件中,添加:

  import config

  app = Flask(__name__)

  在这添加config内容:

  app.config.from_object(config)  #通过这种方式添加配置文件

  备注:

  SECRET_KEY和SQLCHAMY均可以放在config.py文件中使用

  二、路由

  1、普通路由,带字符串式

@app.route('/user/<username>')
def user(username):
return 'User %s' % username

  

  2、带数字

  分类:

    1、int

    2、float

    3、path

@app.route('/user1/<int:user_id>')
def user1(user_id):
return 'User_id %s' % user_id

int类型

  

  3、正则表达式方式URL

from flask import Flask, render_template
from werkzeug.routing import BaseConverter class RegexConverter(BaseConverter): def __init__(self,url_map,*items):
super(RegexConverter,self).__init__(url_map)
self.regex = items[0] app = Flask(__name__) app.url_map.converters['regex'] = RegexConverter @app.route('/user2/<regex("[a-z]{3}"):user2_id>')
def user2(user2_id):
return 'user2 %s' % user2_id

  4、url的类型:

  在app.route中的关键字定义有两种:

  • @app.route('/about')   文件名类型,后面不能加‘/’ 这个类似于文件名
  • @app.route('/projects/')  文件夹类型,后面还可以跟文件名

  

  URL反转:

  from flask import Flask,url_for

  @app.route('/')

  def index():

    print(url_for('my_list'))  #通过url_for方式可以将my_list对应的URL打印出来,这种方式通常用于template的文件中,用这种方式映射,在修改了url后,由于url_for对应的是函数名称,所以不受影响,仍然可以映射到正确的视图函数

    print(url_for('article',id='abc'))

    return 'Hello World'

  @app.roue('/list')

  def my_list():

    return 'list'

  @app.route('/article/<id>/')

  def article(id):

    return '你请求的id是%s' %id

反转URL:

  1、什么叫反转URL:从视图函数到url的转换叫反转url

  2、反转url用处:

    在页面重定向时候,会使用url反转

    在模板中,也会使用url反转

  5、Flask中一个views函数对应多个URL

@app.route('/projects/')
@app.route('/program/')
def projects():
return 'The Projects Page'

  6、POST与GET方法

@app.route('/login', methods=['GET', 'POST'])
def login():
if request.method == 'POST':
username = request.form['username']
password = request.form['password']
print(username, password)
return redirect(url_for('index'))
# else:
# username = request.args['username'] return render_template('login.html', method=request.method)

  7、上传文件

@app.route('/uploads', methods=['GET', 'POST'])
def uploads():
if request.method == 'POST':
f = request.files['file']
print(f.filename)
basepath = path.abspath(path.dirname(__file__))
upload_path = path.join(basepath, 'static/uploads')
f.save(path.join(upload_path, secure_filename(f.filename)))
return redirect(url_for('uploads'))
return render_template('upload.html')
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<form action="/uploads" method="POST" enctype="multipart/form-data">
<input type="file" name="file"/>
<input type="submit" value="提交"/>
</form>
</body>
</html>

load.html

  8、cookie

@app.route('/projects/')
@app.route('/program/')
def projects():
request.cookies['username'] #获取cookie
return 'The Projects Page'

获取cookie

from flask import Flask, render_template, request, redirect, url_for, make_response
from werkzeug.routing import BaseConverter
from os import path
from werkzeug.utils import secure_filename @app.route('/')
def hello_world():
response = make_response(render_template('index.html', title='welcome '))
response.set_cookie('username','a') #设置cookie return response

设置cookie

  9、自定义错误代码页面

app.route('/users/<user_id>')
def users(user_id):
if int(user_id) == 1:
return render_template("user.html")
else:
abort(404) #定义异常代码以便被异常方法捕获

正常用户界面

@app.errorhandler(404)
def page_not_found(error):
return render_template('404.html'), 404
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<h1>404</h1>
<h1>很抱歉!</h1>
<p>访问的页面不存在</p>
</body>
</html>

404.html

  10、消息捕获:

  后端通过flash方法发送提示,前端通过get_flashed_messages()[0]方法来获取提示

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<h1>{{ get_flashed_messages()[0] }}</h1> //由于消息只有一条消息,所以消息提示的数组使用第一条记录
</body>
</html>

前端

from flask import Flask, flash, render_template

app = Flask(__name__)

app.secret_key = '' #当消息提示时会使用秘钥进行加密
@app.route('/')
def hello_world():
flash('hello user')
return render_template('index.html')

后端

  二、包管理

  通过pip命令生成一个requirements文件

  . venv/bin/active

  pip freeze > requirements.txt 生成一个文件

  如果要安装的话:

  pip install -r requirements.txt

  安装包:

  Flask_Script

  

from flask import Flask, render_template, request, redirect, url_for, make_response, abort
from werkzeug.routing import BaseConverter
from os import path
from werkzeug.utils import secure_filename
from flask_script import Manager
# from flask.ext.script import Manager class RegexConverter(BaseConverter):
def __init__(self, url_map, *items):
super(RegexConverter, self).__init__(url_map)
self.regex = items[0] app = Flask(__name__)
# UPLOAD_FOLDER = 'static/uploads/'
# app.config['UPLOAD_FOLDER'] = UPLOAD_FOLDER
app.url_map.converters['regex'] = RegexConverter
manager = Manager(app) @app.route('/user2/<regex("[a-z]{3}"):user2_id>')
def user2(user2_id):
return 'user2 %s' % user2_id @app.route('/')
def index():
# abort(404)
response = make_response(render_template('index.html', title='welcome '))
response.set_cookie('username','a') #设置cookie return response @app.errorhandler(404)
def page_not_found(error):
return render_template('404.html'), 404 @app.route('/services')
def services():
return 'Services' @app.route('/user/<username>')
def user(username):
return 'User %s' % username @app.route('/user1/<int:user_id>')
def user1(user_id):
return 'User_id %s' % user_id @app.route('/about')
def about():
return 'About' @app.route('/projects/')
@app.route('/program/')
def projects():
request.cookies['username'] #获取cookie
return 'The Projects Page' @app.route('/login', methods=['GET', 'POST'])
def login():
if request.method == 'POST':
username = request.form['username']
password = request.form['password']
print(username, password)
return redirect(url_for('index'))
# else:
# username = request.args['username'] return render_template('login.html', method=request.method) @app.route('/uploads', methods=['GET', 'POST'])
def uploads():
if request.method == 'POST':
f = request.files['file']
print(f.filename)
basepath = path.abspath(path.dirname(__file__))
upload_path = path.join(basepath, 'static/uploads')
f.save(path.join(upload_path, secure_filename(f.filename)))
return redirect(url_for('uploads'))
return render_template('upload.html') if __name__ == '__main__':
# app.run(debug=True)
manager.run()

通过终端运行python3 learn_flask.py runserver

  三、jinjia2模板

  首先创建flask项目后 ,需要写两个文件夹,static和template

  在template目录里写一个index.html文件:

  <body>

    <p>用户名:{{ username }}</p>

    <p>年龄:{{ age }}</p>

    <p>性别:{{ gender }}</p>

  </body>

  在视图函数里添加:

  from flask import Flask,render_template

  @app.route('/')

  def index():

    contex ={

        'username': 'gavin',

        'age': '18',

        ''gender:'male',

        }

    return render_template('index.html',**context)  #如果有多个参数需要传递,可以使用字典的方式进行传参

 

  在模板中如果要使用一般变量,语法{{变量名}}

  访问模型中的属性或者字典,可以通过‘{{ params.property }}’的形式,或者是使用{{ params['age'] }}的形式

  例子:

    index.html中:

    <p>{{ person.name }}</p>

    <p>{{ person.age }}</p>

    <p>{{ websites.baidu }}</p>

    <p>{{ websites.google }}</p>

  视图函数中:

  

from flask import Flask,render_template

  @app.route('/')

  def index():

    class Person(object):

      name = 'gavin'

      age = 18

    p = Person()

    contex ={

        'username': 'gavin',

        'age': '18',

        ''gender:'male',

        'person': p,

        'websites':{

          'baidu': 'www.baidu.com',

          'google': 'www.google.com.hk',

             },

        }

    return render_template('index.html',**context)

   备注:

   在jinjia2中可以针对传递的变量的索引进行操作:

    例子:

    1、 {% if loop.index is odd %}| {% endif %} 如果索引为奇数,加 |

    2、{% if not loop.first %} |{% endif %}   如果不是第一个索引,加 |

  2、if判断:

    index.html中:

    {% if user and user.age > 18 %}

    {{内容}}

    {% else %}

    {{内容}}

    {% endif %}

   3、for循环

    字典的遍历:可以使用items()/keys()/values()/iteritems()/iterkeys()/itervalues()

    index.html中:

    {% for k,v in user.items() %}

    <p>{{k}}: {{v}}</p>

    {% endfor%}

    列表的遍历:

    {% for a in list1 %}

      {{a}} 

    {% endfor %}

    4、过滤器

    介绍:可以处理变量,原始的变量经过处理后展示出来,作用的对象的变量

    语法:

      {{  avater|default(‘xxx’)}}  如果当前变量不存在,可以指定默认值

      <p>评论数 {{  comments|length }}</p>  求列表、字符串、字典、元组的长度

      

    5、继承

    作用:可以把一些公共的代码放在base模板中

    语法:

    {% extends  ‘base.html’%}

    {%block XXX%}

    {% endblock %}

    block实现:

    作用:可以让子模板实现一些自己的需求,父模板必须定义好

    子模板中的代码,必须放在block块中

  四、URL链接和静态文件

    url链接:使用url_for(‘视图函数名称’),可以反正url

    加载静态文件:

    1、语法:‘url_for('static',filename='路径')’

    2、静态文件,flask会从static文件夹汇总开始寻找,所以不需要再写static这个路径了

    3、可以加载css文件、js文件、iamge文件

    例子:

    首先static目录下建立css目录,在css目录下建立index.css文件

    然后在index.html中添加<link rel='stylesheet' href="{{ url_for('static',filename="css/index.css") }}"> 

  

  五、SQLAlchemy:

    配置文件:

    config.py:

    DIALECT = 'mysql'

    DRIVER = 'mysqldb'

    USRNAME = 'root'

    PASSWORD = 'root'

    HOST = '127.0.0.1'

    PORT = '3306'

    DATABASE = 'db_demo1'

    SQLALCHEMY_DATABASE_URI = "{}+{}://{}:{}@{}:{}/{}?charset=utf8".format(DIALECT,DRIVER,USRNAME,PASSWORD,HOST,PORT,DATABASE)

    SQLALCHEMY_TRACK_MODIFICATIONS = True

    

    视图函数:

    from flask_sqlalchemy import SQLAlchemy

    import config

    app = Flask(__name__)

    app.config.from_object(config)

    db = SQLALchemy(app)

    #article表

    class Article(db.Model):

      __tablename__ = 'article'

      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)

    db.create_all()#创建表

    

    对数据库进行增删改查操作:

         

    视图函数中:

    @app.route('/')

    def index():

      #增加

      article = Article(title='a',content='b')

      db.session.add(article)

      #事务操作(必须有commit才进行操作,上面操作还没有进行事务操作)

      db.session.commit()#完成事务操作后才真正写入数据库中

      

    #查

    @app.route('/')

    def index():

      result = Article.query.filter(Article.title=='a').all()  #query是专门用于查找的,query是从db.Model中继承下来的,这里返回的是Query对象,如果想只取第一个对象,可以使用first()代替all()     

      print(result[0].title,result[0].content) 

    #改

    1、先把要改的数据查找出来

    2、对该数据进行更改

    3、做事务提交

    article = Article.query.filter(Article.title='a').first()

    article.title = 'new title'

    db.session.commit()

    

    #删

    article = Article.query.filter(Article.title='a').first()

    db.session.delete(article)

    db.session.commit()

    

    外键约束:

    语法:

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

      author = db.relationship('User',backref=db.backref('articles'))#这个模型添加一个author属性,可以访问这篇文章的作者的数据,像访问普通模型一样

      backref是定义反向引用,可以通过User.articles这个模型访问这个模型所写的所有文章      

    

    例子:

    首先创建了两个表

    class User(db.Model):

      __tablename__ = 'user'

      id = db.Column(db.Integer,primary_key=True,autoincrement=True)

      username = db.Column(db.String(100),nullable=False)

    class Article(db.Model):  

      __tablename__ = 'article'

      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'))   #第一个参数是管理到那个模型的名字

    db.create_all()

    

    #添加文章与用户    

    @app.route('/')

    def index():

      user1 = User(username='gavin')

      db.session.add(user1)

      article = Article(title='a',content='b')

      article.author = User.query.filter(id==1).first() #在添加作者时通过author方式进行添加

      db.session.add(aricle)

      db.session.commit()  

      #需求:要找标题为a的文章的作者    

      article = Article.query.filter(Article.title=='a').first()  

      print(article.author.username) #通过title查找作者

      #需求:找到作者写过的所有文章

      author = User.query.filtr(User.username=='gavin').first()

      result = author.articles

      for article in result:

        print(print.article.title)

   

    多对多:

    article_tag = db.Table('article_tag'

            db.Column('article_id',db.Integer,db.ForeignKey('article_id'),primary_key=True),

            db.Column('tag_id', db.Integer.db.ForeighKey('tag_id'),primary_key=True),

            

          )

    class Article(db.Model):  

      __tablename__ = 'article'

      id = db.Column(db.Integer,primary_key=True,autoincrement=True)

      title = db.Column(db.String(100),nullable=False)

      tags = db.relationship('Tag', secondary=article_tag,backhref=db.backhref('articles'))

    class Tag(db.Model):  

      __tablename__ = 'tag'

      id = db.Column(db.Integer,primary_key=True,autoincrement=True)

      name = db.Column(db.String(100),nullable=False)

   

    db.create_all()

    

    @app.route('/')

    def index():

      article1 = Article(title='aaa')

      article2 = Article(title='bbb') 

      

      tag1 = Tag(name='111')  

      tag2 = Tag(name='222')  

      article1.tags.append(tag1)

      article1.tags.append(tag2)

      article2.tags.append(tag1)

      article.2tags.append(tag2)

      db.session.add_all(article1,article2,tag1,tag2) 

      db.session.commit()

      article1 = Article.query.filter(Article.title=='aaa').first()

      tags = article1.tags

      for tag in tags:

        print(tag.name)

           

 备注:

  如果要求前端显示按照顺序进行,可以添加:order_by(),在括号内需要添加models里对应数据库函数对应的条目,例如order_by('create_time')

就是按照创建时间来排序,按照正序方式进行,如果想倒序,只需要order_by('-create_time')方式来进行

  六、flask-script

    作用:通过命令行的形式操作flask,例如通过命令跑一个并发版本的服务器,设置数据库,定时任务等,要使用flask-scrtipt,可以通过pip install flask-script安装最新版本,首先看一个简单的例子:

    创建一个manager.py文件:

    from flask_script import Manager

    from your_app import app

    manager = Manager(app)

    @manager.command

    def hello():

      print('hello')

    if __name__ == '__main__':

      manager.run()

    可以在script中完成数据库操作:

    1、创建一个db_scrtipt.py文件

    from flask_script import Manager

    DBmanager = Manger()

    @DBmanager.command

    def init():

      print('数据库初始化完成')

    @DBmanager.command

    def migrate():

      print('数据表迁移完成')

    回到manage.py文件中添加:

    

    from flask_script import Manager

    from your_app import app

    from db_script import DBmanager

    manager = Manager(app)

    @manager.command

    def hello():

      print('hello')

    manager.add_command('db',DBmanager)  #db表示想要操作DBmanager的话使用的一个标示,可以是任意,后面DBmanger表示引用

    if __name__ == '__main__':

      manager.run()

    

    执行操作:

    python3 manage.py db init #完成初始化操作

    python3 manage.py db migrate #完成迁移操作

    定义命令的三种方法:

    1、使用@command装饰器

    2、使用类继承自Command类:

       

  七、分开models和解决循环引用

    1、分开models的目的,是为了代码简洁

    2、解决循环引用的方法,把db放在另外一个文件中,切断循环引用

  

  八、flask_migrate

    

    例子:

    1、创建exts.py文件:

     from flask_sqlalchemy import SQLAlchemy

     db = SQLAlchemy()

    2、创建models.py文件

     from exts import db

    

     def Article(db.Model):

        __tablename__ = 'article' 

        id = db.Column(db.Integer,primary_key= True,autocrement=True)

        title = db.Column(db.String(100),nullable=False) 

    3、config.py文件   

    DIALECT = 'mysql'

    DRIVER = 'mysqldb'

    USRNAME = 'root'

    PASSWORD = 'root'

    HOST = '127.0.0.1'

    PORT = '3306'

    DATABASE = 'db_demo1'

    SQLALCHEMY_DATABASE_URI = "{}+{}://{}:{}@{}:{}/{}?charset=utf8".format(DIALECT,DRIVER,USRNAME,PASSWORD,HOST,PORT,DATABASE)

    SQLALCHEMY_TRACK_MODIFICATIONS = True

     

    4、视图函数

    from flask import Flask 

    from exts import db

    from models import Article

    import config

    app = Flask(__name__)

    app.config.from_object(config)

    db.init_app(app) #由于exts没有指定哪个数据库,所以需要在这里重新指定    

    with app.app_context():

      db.create_all()      

   如果此时要添加数据库的结构,需要进行migrate

    1、介绍:因为采用db.create_all()在后期修改字段的时候,不会字段的映射到数据库中,必须删除表,然后重新运行,这样不符合我的要求,因此flask-migrate就是为了解决这种歌问题,它可以在每次修改模型后,可以将修改的东西映射到数据库中

    2、首先进入到虚拟机环境中,然后使用pip install flask_migrate进行安装

  使用:

    1、flask-script方式

  首先创建manage.py文件 : 

    from flask_script import Manager

    from <视图函数名字> import app

    from flask_migrate import Migrate,MigrateCommand

    from models import Article #需要导入这个,migrate才知道要对哪个表进行迁移

    from exts import db

    manager = Manager(app)

    #1、要使用flask_migrate,必须绑定db和app

    migrate = Migrate(app,db)

    #2、把MigrateCommand命令加到manager中

    manager.add_command('db', MigrateCommand)

    if __name__ == '__main__':

      manager.run()

    其次回到视图函数中,将

    with app.app_context():

      db.create_all() 

    条目删除

    最后执行:#模型-->迁移文件 --> 表

    python manage.py db init  #生成migrate文件夹

    python manage.py db migrate #将模型生成迁移文件 

    python manage.py db upgrade #将迁移文件生成表

       

    

    

 九、cookie和session

   1、cookie:出现原因:在网站里,http请求是无状态的,也就是说即使第一次和服务器连接后并且登录成功,第二次请求服务器依然不知道当前请求是哪个用户,cookie的出现就是为了解决这个问题,第一次登录服务器返回一个数据cookie给浏览器,然后浏览器保存再本地,当该用户第二次请求时,就会自动把上次请求存储的cookie数据字典携带给服务器,服务器通过浏览器携带的数据就能判断当前用户是哪个

   2、如果服务器返回了cookie给浏览器,那么浏览器下次再请求相同的服务器时,会自动把cookie发送给服务器,这个过程中,用户不需要管

   3、cookie是保存在浏览器中,相对的的是浏览器

     session:

   1、session介绍:session和cookie的作用类似都是为了保存用户相关形象,不同的是cookie是存储在浏览器,而session是存储在服务器,存在服务器的数据更加安全,不容易被窃取,但存储在服务器也有一定的弊端,就是会占用服务器资源,但是现在服务器发展到今天,这些session新潮存储绰绰有余

   2、使用session的好处:

    敏感数据不是直接发送给浏览器,而是发送回一个session_id 服务器将session_id和敏感数据做一个映射存储在session(服务器上面)中,更加安全

    session可以设置过期时间,也从另外一个方面,保存了用户的账号安全

   flask中session工作机制:

    flask中的session机制:把敏感数据加密后放入session中,再把session存放在cookie中,下次请求的时候,再从浏览器发送过来的cookie中读取session,在从session中读取敏感数据,并进行解密,获取最终数据

    flask的这种session机制,可以节省服务器开销,因为把所有的信息都存在到了客户端(浏览器)

    安全是相对的,吧session放到cookie中也是经过加密的

   例子:

    视图函数:

    

    from flask import Flask,session 

    app = Flask(__name__)

    #添加数据到session中

    #操作session的时候,和操作字典是一样的

    #SECRET_KEY 放在config.py文件中,或者直接单独设置

    import os

    #app.config[SECRET_KEY] = '必须24个字符的字符串'

    app.config['SECRET_KEY'] = os.urandom(24)

    #如果不想超时时间为31天(默认)可以按照如下设置

    from datetime import timedelta

    app.config['PERMANENT_SESSION_LIFETIME'] = timedelta(days=7)

    @app.route('/')

    def hello_world():

      #如果没有指定session过期时间,那么在浏览器结束就过期

      session['username'] = 'gavin'

      #如果设置session.permanent=True,默认情况下(没有设置app.config['PERMANENT_SESSION_LIFETIME'] = timedelta(XX))session的超时时间为31天

      session.permanent = True

      return 'hellow world'

    @app.route('/get/')

    def get():

      #获取session,如果不存在会返回None

      return session.get('username')

    @app.route('/delete')

    def delete():

      print(session.get('username'))

      #删除session

      session.pop('username')

      print session.get('username')

      return 'success'

    

    @app.route('/clear/')

    def clear():

      print(session.get('username'))

      #删除session中的所有数据

      session.clear()

      print session.get('username')

      return 'success'

    

    if __name__ == '__main__':

      app.run(debug=True)

  十、get与post请求

    1、get请求:

      使用场景:如果只对服务器获取数据不对服务器产生影响,使用get请求

      传参: get请求传参是放在url中并且是通过?的形式来指定key和value的

    2、post请求:

      使用场景:如果要对服务器产生影响,使用post请求

      传参:post请求传参是通过form data的形式发送给服务器

    例子:   

    from flask import Flask,render_tempalte,request 

    app = Flask(__name__)

    @app.route('/')

    def index():

      return render_template('index.html')

    @app.route('/search/')

    def search():

      #arguments,以字典的形式获取url中所有参数

      print(request.args) #get请求可以通过request.args来获取数据,post请求可以通过request.form.get来获取数据

      return 'success'

    #默认的视图函数只能采用get请求,如果要采用post请求,要单独说明

    @app.route('/login/',method=['GET','POST'])

    def login():

      if request.method == 'POST':

        username = request.form.get('username')

        password = request.form.get('password')

        

      return 'login'

    在index.html中:

    <a href="{{  urlf_for('search',q="hello")}}">跳转到搜索</a>

    在login.html中:

    <form action='{{ url_for('login')}}' method='post'>

      <input type='text' name="username"/>

      <input type='password'  name='password'/>

      <inpu ttype='submit' />

    </form>

    

  十一、g变量

  g变量就是global的简称,可以使用:

  from flask import g的方式调用,

  在g变量中可以使用类似于jinjia2的方式赋值,g.username = ‘gavin’  、g.password=123

  在g变量引入后,在整个项目的其他文件想引用,可以直接从from flask import g后直接引用,无序通过传参方式赋值,但是g只在每一次请求时生效,等下一次请求时g会被第二次赋值,就不是原来的数据了

  十二、钩子函数

    1、before_request 在任何请求之前执行,在执行完毕后再执行视图函数中其他函数,这个代码只是一个装饰器,它可以把需要设置为钩子函数的代码放到视图函数执行之前来执行

    例子:

    视图函数:

    from flask import Flask,render_template,request,session,redirect,url_for,g

    import os

    app = Flask(__name__)

    app.config['SECRET_KEY'] = os.urandom(24)

    @app.route('/')

    def index():

    return render_to_template('index.html')

    @app.route('/login',methods=['GET','POST'])

    def login():

      if request.method == 'post':

        username = request.form.get('username')

        password = request.form.get('password')

        if username == 'gavin' and password == '123':

          session['username'] == username

          return 'success'

        else:

          return 'fail to login'

      return render_template('login.html')

    @app.route('/edit/')

    def edit():

      

        

      if hasattr(g,'username'):

        return '修改成功'

      else:

        return direct(url_for('login'))

    

    @app.before_request

    def my_before_request():

      user_id = session.get('user_id')

      user = User.query.filter(User.id == user_id).first()

      if session.get('username'):

        g.username = session.get('username')

               

    if __name__ == '__main__':

      app.run(debug=True)

    

    在login.html中:

    <form action='{{ url_for('login')}}' method='post'>

      <input type='text' name="username"/>

      <input type='password'  name='password'/>

      <inpu ttype='submit' />

    </form>

    

    2、context_processor

       上下文处理器应该返回一个字典,字典中的key会被模板中当做变量来渲染

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

         被这个装饰器修饰的钩子函数,必须返回一个字典,即使是空的字典

    例子:

    from flask import Flask,render_template,request,session,redirect,url_for,g

    import os

    app = Flask(__name__)

    app.config['SECRET_KEY'] = os.urandom(24)

    @app.route('/')

    def index():

    return render_to_template('index.html')#有了context_processor以后,不需要在这里传递参数,template里的html文件照样可以接收模板文件

    @app.route('/login',methods=['GET','POST'])

    def login():

      if request.method == 'post':

        username = request.form.get('username')

        password = request.form.get('password')

        if username == 'gavin' and password == '123':

          session['username'] == username

          return 'success'

        else:

          return 'fail to login'

      return render_template('login.html')

    @app.route('/edit/')

    def edit():

      

        

      if hasattr(g,'username'):

        return '修改成功'

      else:

        return direct(url_for('login'))

    

    @app.before_request

    def my_before_request():

      user_id = session.get('user_id')

      user = User.query.filter(User.id == user_id).first()

      if session.get('username'):

        g.username = session.get('username',)

    @app.context_processor

    def my_context_processor():

      username = session.get('username')

      if username:

        return {'username': username} #返回了这个字典,在所有模板里都会把这个当做模板去渲染

              

    if __name__ == '__main__':

      app.run(debug=True)

  十二、livereload方法

    livereload方法可以实现自动加载任意修改的界面     

from flask import Flask, render_template
from livereload import Server app = Flask(__name__) @app.route('/')
def index():
return render_template('index.html', title="<h1>Hello World!</h1>") if __name__ == '__main__':
#导入app.wsgi服务
live_server = Server(app.wsgi_app)
#watch用来监控哪个界面,这种方式表示所有页面
live_server.watch('**/*.*')
#开启livereload服务
live_server.serve(open_url_delay=True)

  十三、表单

  备注:

   首先表单提交需要避免跨站请求攻击CSRF

  创建一个config.py文件

import os

DEBUG = True

SECRET_KEY = os.urandom(24)

config.py

  创建forms.py文件,里面填写表单内容

from flask_wtf import Form
from wtforms import StringField, PasswordField, SubmitField
from wtforms.validators import DataRequired class LoginForm(Form):
#DataRequired()要求这个字段必须有值
username = StringField(label="用户名", validators=[DataRequired()])
password = PasswordField(label="密码", validators=[DataRequired()])
submit = SubmitField(label="提交")

  主配置文件中引入该forms.py文件

from flask import Flask, render_template
from livereload import Server
from flask_bootstrap import Bootstrap import config app = Flask(__name__)
app.config.from_object(config)
bootstrap = Bootstrap(app) @app.route('/login/',methods=['GET','POSt'])
def login():
from forms import LoginForm
form = LoginForm()
return render_template('login.html',title="登录",form=form)

  在login.html文件中添加

{% extends "bootstrap/base.html" %}
{% block content %}
<div class="container">
<form action="{{ url_for('login') }}" method="POSt"> {{ form.username.label }}
{{ form.username() }}
{{ form.password.label }}
{{ form.password() }}
{{form.submit() }}
</form>
</div>
{% endblock %}

  wtf表单样式与校验器样式:

 

  校验器样式:

  十四、消息提示和异常处理

  消息提示:

  在登录页面,如果有步骤错误,比如没输入用户名或密码,都会有消息提示,在flask中使用flash()方式进行消息提示,这个提示在前端html中,使用{{get_flashed_messages()}}方式来获取

from flask import Flask, flash, render_template, request

app = Flask(__name__)
#flask在使用消息提示时,会使用secret_key进行加密
app.secret_key = '' @app.route('/')
def hello_world():
flash('Hello Gavin')
return render_template('index.html') @app.route('/login',methods=['get','post'])
def login():
username = request.form.get('username')
password = request.form.get('password') if not username:
flash("请输入用户名")
return render_template('index.html')
if not password:
flash('请输入密码')
return render_template('index.html')
elif username == 'gavin' and password == '':
flash('登录成功')
return render_template('index.html')
else:
flash('用户名或密码错误')
return render_template('index.html')
if __name__ == '__main__':
app.run()

  异常处理:

  在页面找不到时,需要做异常处理,返回自己特色的页面,而不是使用flask提供的原生页面

@app.route('/users/<user_id>')
def users(user_id):
if int(user_id) == 1: return render_template('user.html',user_id=user_id)
else:
#如果条件不满足,置为状态码,然后送入到异常处理界面处理
abort(404)
#使用errorhandler来处理404异常,如果捕获到异常就按照下面的函数进行处理
@app.errorhandler(404)
def not_found(error):
return render_template('404.html')

  

Python学习笔记第二十三周(Flask架构)的更多相关文章

  1. Python学习笔记第二十七周(Bootstrap)

    目录: 全局样式 一.栅格系统 二.表单 三.按钮  四.导航 五.按钮组 六.面板 七.表格 八.分页 九.排版 十.图片 十一.辅助类 十二.响应式工具 组件 内容: 前言: 首先通过https: ...

  2. Python学习笔记第二十一周

    目录: 1.URL 2.Models - 操作 3.Templates - html模板的使用 - 自定义函数 4.cookie和session 5.分页(自定义分页) 6.Form验证 内容: 1. ...

  3. Python学习笔记第二十周

    目录: 一.ORM 1.查询补充 备注:forloop.counter介绍 二.Ajax 三.ORM多对多操作 内容: 一.ORM 1.查询补充: 1.models.USR.objects.all() ...

  4. Python学习笔记(十三)

    Python学习笔记(十三): 模块 包 if name == main 软件目录结构规范 作业-ATM+购物商城程序 1. 模块 1. 模块导入方法 import 语句 import module1 ...

  5. python学习笔记第二周

    目录 一.基础概念 1.模块 1)os模块 2)sys模块 2.pyc文件 3.数据类型 1)数字 2)布尔值 3)字符串 4.数据运算 5.运算符 6.赋值运算 7.逻辑运算 8.成员运算 9.身份 ...

  6. Python学习笔记第二十五周(Django补充)

    1.render_to_reponse() 不同于render,render_to_response()不用包含request,直接写template中文件 2.locals() 如果views文件中 ...

  7. Python学习笔记第二十六周(Django补充)

    一.基于jQuery的ajax实现(最底层方法:$.jax()) $.ajax( url: type:''POST“ ) $.get(url,[data],[callback],[type])  #c ...

  8. Python学习笔记第二十二周(前端知识点补充)

    目录: 一.伪类 二.样式 1.字体 2.背景图片 3.margin和padding 4.列表属性 5.float 6.clear 7.position 8.text-decoration(a标签下划 ...

  9. 菜鸟Python学习笔记第二天:关于Python黑客。

    2016年1月5日 星期四 天气:还好 一直不知道自己为什么要去学Python,其实Python能做到的Java都可以做到,Python有的有点Java也有,而且Java还是必修课,可是就是不愿意去学 ...

随机推荐

  1. log4j的一些参数说明

    参数 说明 例子 %c 列出logger名字空间的全称,如果加上{<层数>}表示列出从最内层算起的指定层数的名字空间 log4j配置文件参数举例 输出显示媒介 假设当前logger名字空间 ...

  2. [CodeForces - 614E] E - Necklace

    E - Necklace Ivan wants to make a necklace as a present to his beloved girl. A necklace is a cyclic ...

  3. Linux -- 之HDFS实现自动切换HA(全新HDFS)

    Linux -- 之HDFS实现自动切换HA(全新HDFS) JDK规划 1.7及以上  https://blog.csdn.net/meiLin_Ya/article/details/8065094 ...

  4. AWVS和AppScan使用代理进行扫描教程

    一.说明 扫描网站时,一是可能某些网站网络不能直接访问,二是可能不想曝露本机IP.这时要进行处理. 第一个方法是如果有vpn直接登vpn,vpn的话由于是直接修改操作系统层次的网络,扫描器不需要额外做 ...

  5. JBoss/WildFly 初步安装配置教程

    1.下载 Redhat的JBoss与Oracle的Weblogic.IBM的WebSphere并称三大JAVA EE中间件. JBoss AS是JBoss的开源版本,JBoss EAP是JBoss的企 ...

  6. 面向对象的Java实现

    1.面向对象的Java实现--封装 1-1:封装 a.为什么需要封装(封装可以是数据方便维护.增加实用性.方便扩展等等.通过面向对象的思想,模拟现实生活中的事物.) b.什么是封装(封装就是将属性私有 ...

  7. C++11 并发之std::thread std::mutex

    https://www.cnblogs.com/whlook/p/6573659.html (https://www.cnblogs.com/lidabo/p/7852033.html) C++:线程 ...

  8. 机器学习---笔记----Python基础

    一. python简介 1. python 具有丰富强大的库,常被称为胶水语言,能够把用其他语言制作的各种模块很轻松地联结在一起 2. python强制使用空白符(white space)作为语句缩进 ...

  9. java将字符串根据空格进行分割,使用split方法

    public class D { public static void main(String[] args) { String b = "Hello Java World"; S ...

  10. day03 is 与== 常量

    is身份运算:比较的是id是否相等 ==判断值是否相等 ... 值相等id不一定相等 >>>x=1111111111111111111111111111111111111111111 ...