Flask框架学习

本文详细介绍了Flask框架,强调其轻量级和灵活性,对比了Django和Tornado。文章深入讲解了Flask的配置方式、路由系统、Jinja2模板语言的使用,包括模板标签、过滤器和宏。还涵盖了请求和响应处理、Web表单、CSRF保护、Flask-WTF验证器、SQL、session和cookie的管理,以及Flask的扩展和中间件功能。此外,讨论了使用Flask-Bootstrap集成Twitter Bootstrap的方法,以及Flask-RESTful构建REST API的基本概念。
摘要由CSDN通过智能技术生成

Flask、Django、Tornado框架

django:重武器,内部包含了非常多的组件:orm、form、modelform、缓存、Session、中间件、信号等…
flask:短小精悍,内部没有太多组件。第三方组件非常丰富。 小型项目玩速度,大型项目无压力。路由是由装饰器实现。本质add_url_rule实现,只要用的好,毛坯房变成总统套
Tornado:异步非阻塞框架(node.js)
bottle:更加简洁,企业级用的少
web.py:用的少

Flask介绍`

配置文件Flask

方式一:app.config[‘debug’] = True
方式二:app.debug = True
方式三:最常用方式:创建一个setting的py文件,通过类或继承导入
app.config.from_object(“path.Class(exp:settings.DevelopmentConfig)”)

路由系统

@app.route()和app.add_url_rule参数

        rule,                       URL规则
        view_func,                  视图函数名称 
        defaults=None,              默认值,当URL中无参数,函数需要参数时,使用defaults={'k':'v'}为函数提供参数
        endpoint=None,              名称,用于反向生成URL,即: url_for('名称')
        methods=None,               允许的请求方式,如:["GET","POST"]

ps:hosts文件
c:\windows\system\drivers\etc\hosts

模板语言(jinja2)

模板是一个包含响应文本的文件,其中包含用占位变量表示的动态部分,其具体值只在请
求的上下文中才能知道。使用真实值替换变量,再返回最终得到的响应字符串,这一过程
称为渲染。为了渲染模板,Flask 使用了一个名为 Jinja2 的强大模板引擎。
template

模板标签:

jinja2默认配置:
所有扩展名为 .html 、 .htm 、 .xml 以及 .xhtml 的模板会开启自动转义
模板可以利用 {% autoescape %} 标签选择自动转义的开关。

变量:
{{ name }}结构表示一个变量 它是一种特殊的占位符,告诉模板引擎这个位置的值
从渲染模板是使用的数据获取
Jinja2 能识别所有类型的变量,甚至是一些复杂的类型,例如列表、字典和对象。在模板
中使用变量的一些示例如下:

A value from a dictionary: {{ mydict['key'] }}.

A value from a list: {{ mylist[3] }}.

A value from a list, with a variable index: {{ mylist[myintvar] }}.

A value from an object's method: {{ myobj.somemethod() }}.

1、{% if %}{% endif %}--------------控制语句
2、{% for foo in config %}{% endfor %}----------循环语句
3、{% block [自定义名称] %}---------继承标签(父类中使用)
  在子类中通过
  {% extends ’继承模板路径‘ %}
  先导入要继承的模板【比如html】,再通过
  {% block [自定义名称] %}
  修改模板的内容。
  {{ super()}}
  标签可以用来控制是否继承父类的初始元素,内容以及出现的顺序。
4、{% include ‘继承模板路径’ %}-----------包含标签,将一个模板的内容照搬
exp:
在这里插入图片描述
base1.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>{% block title %}{% endblock %}</title>
</head>
<body>
    <h3>狗的但二</h3>
    {% block h4 %}
        <h4>目的地的</h4>
    {% endblock %}
    {% include 'father/footer.html' %}
</body>
</html>

footer.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <a href="#">百度</a>
    <a href="#">百度</a>
    <a href="#">百度</a>
    <a href="#">百度</a>
    <p>~~~~~~~~~~~~~</p>
</body>
</html>

son1.html

{% extends ‘father/base1.html’ %}

{% block title %} 狗子王 {% endblock %}

{% block h4 %}

<h5>我不行了</h5>
{{ super() }}

{% endblock %}

{% if %}{% endif %}
{% for foo in config %}{% endfor %}
{% block [自定义名称] %}

{% extends ’继承模板路径‘ %}

{% include ‘继承模板路径’ %}

可以同过调整 h5标签和 {{ super() }} 的位置改变显示顺序

模板过滤器

语法 {{ ‘变量’ | 过滤器}}
常用过滤器:

upper:  全部大写

lower:   全部小写

title:   对每个单词的首字母大写

capitalize: 对首字母大写

reverse: 字符串倒序

sum : 数字列表求和

safe: 渲染时不做转义

完整的过滤器列表可在 Jinja2 文档(http://jinja.pocoo.org/docs/templates/#builtin-filters)中
查看。

宏(macro)

类似python中的函数
先定义:

{% macro first_macor(things) %}
    <ol>
        {% for thing in first_macor %}
    
            <li>{{ thing }}</li>
    
        {% endfor %}
    </ol>
{% endmacro %}

每次在一个模板中先导入:

<!DOCTYPE html>
{% import 'father/macro_demo.html' as tool %}
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    {{ tool.first_macor("通过视图传的参数") }}
</body>
</html>

相当于一个封装:将一些方法封装以后,在导入直接调用。。。不常用

使用Flask-Bootstrap集成Twitter Bootstrap

pip install flask-bootstarp
初始化 Flask-Bootstrap 之后,就可以在程序中使用一个包含所有 Bootstrap 文件的基模板。
这个模板利用 Jinja2 的模板继承机制,让程序扩展一个具有基本页面结构的基模板,其中
就有用来引入 Bootstrap 的元素。

Bootstrap 官方文档(http://getbootstrap.com/)是很
好的学习资源,有很多可以直接复制粘贴的示例。

请求&和响应

from flask import Flask
from flask import request
from flask import render_template
from flask import redirect
from flask import make_response

app = Flask(__name__)


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

    # 请求相关信息
    # request.method
    # request.args
    # request.form
    # request.values
    # request.cookies
    # request.headers
    # request.path
    # request.full_path
    # request.script_root
    # request.url
    # request.base_url
    # request.url_root
    # request.host_url
    # request.host
    # request.files
    # obj = request.files['the_file_name']
    # obj.save('/var/www/uploads/' + secure_filename(f.filename))

    # 响应相关信息
    # return "字符串"
    # return render_template('html模板路径',**{})
    # return redirect('/index.html')

    # response = make_response(render_template('index.html'))
    # response是flask.wrappers.Response类型
    # response.delete_cookie('key')
    # response.set_cookie('key', 'value')
    # response.headers['X-Something'] = 'A value'
    # return response


    return "内容"

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

Web表单

Flask 的请求对象提供的信息足够用于处理 Web 表单,但有些任务很单调,而且要重复操作,request.form 能获取POST 请求中提交的表单数据

Flask-WTF(http://pythonhosted.org/Flask-WTF/)扩展可以把处理 Web 表单的过程变成一种愉悦的体验。WTForms(http://wtforms.simplecodes.com)包进行了包装,方便集成到 Flask 程序中。

pip install flask-wtf

CSRF攻击

CSRF(cross site request forgery,跨站域请求伪造)是一种网络攻击方式。比如SQL脚本注入,
CSRF攻击原理
网站是通过cookie来实现登录功能的,而cookie只要存在浏览器中,那么浏览器在梵文这个cookie的服务器的时候,就会自动的携带cookie信息到服务器撒谎功能区,那么这时候就存在一个漏洞,如果你访问了一个别有用心的或是病毒网站,这个网站可以在网页源代码中插入js代码,使用js代码给其他服务器发送请求(比如ICBC的转账请求)。那么因为在发送请求的时候,浏览器会自动的把cookie发送给对应的服务器(比如ICBC网站,)就不知道这个请求伪造的,就被欺骗过去了,从而达到在用户不知情的情况下,给某个服务器发送了一个请求(比如转账)。
在这里插入图片描述

跨站请求伪造保护

默认情况下,Flask-WTF 能保护所有表单免受跨站请求伪造(Cross-Site Request Forgery,CSRF)的攻击。恶意网站把请求发送到被攻击者已登录的其他网站时就会引发 CSRF 攻击。为了实现 CSRF 保护,Flask-WTF 需要程序设置一个密钥。Flask-WTF 使用这个密钥生成加密令牌,再用令牌验证请求中表单数据的真伪。

flask-wtf常用的验证器

数据发送过来,经过表单验证,因此需要验证器来进行验证

  • Email:验证上传到额数据是否为邮箱
  • EqualTo:验证上传的数据是否和另一个字段相等
  • InputRequired:原始数据的需要验证,如果不是特殊情况,应该使用InputRequires
  • Length:长度限制,又min和max两个值限制,如果处在两个数字之间则满足。
  • NuberRange:数字区间,又min和max两个值限制,如果处在这两个数字之间则满足。
  • Regexp:自定义正则表达式
  • URL:必须要是URL的形式
  • UUID:验证UUID 自定义验证器: 如果想要对表单中的某个字段进行更细化的验证,那么可以针对这个字段进行单独的验证,步骤如下;
  • 1、定义一个方法,方法名字的规则是:validata_字段名(self,filed)。
  • 2、在方法中,使用‘filed.data’可以获取这个字段具体的值。
  • 3、如果数据马努这个条件,那么可以什么都不做,如果验证失败,那么抛出一个‘wftforms.validators.ValidationError’的异常,并且把验证失败的信息传到这个异常类中。 示例代码:
  • captcha = StringField(validators=[Length(4,4)])
    def validate_captcha(self,field):
    	if field.data != "1234":
    		raise ValidationError("验证码错误!")
    

    文件上传笔记:
    1、在模板中,form表单中,需要指定‘encotype=‘multipart/from-data’’才能上传文件。
    2、在后台如果想要获取上传的文件,那么应该使用‘request.files.get(‘avatar(文件字段名)’)’来获取
    3、保存文件之前,先要使用‘wekzeug.utils.secure_filename’来对上传的文件名进行一个过滤,这样才能保证不会又安全问题(对中文命名的文件不友好,建议英文)
    4、获取到上传的文件后,使用‘avatar.save(路径)方法来保存文件
    5、从服务器上读取文件。应该定义一个url与视图函数,来获取指定的文件。在这个试图函数中,使用‘send_from_directory(文件的目录,文件名)’来获取。

    示例代码

    from flask import Flask,request,render_template, redirect, url_for
    import os
    from werkzeug.utils import secure_filename 
    app = Flask(__name__)
    
    UPLOAD_PATH = os.path.join(os.path.dirname(__file__),"imahes")
    
    @app.route('upload', methods=['Get', 'POST'])
    def upload():
    	if request.method == 'GET':
    		return render_template('upload.html')
    	else:
    		desc = request.form.get('desc')
    		avatar = request.files.get("avatar")
    		filename = secure_filename(avatar.filename)
    		avatar.save(os.path.join(UPLOAD_PATH,filename))
    		return redirect(url_for("get_image",filename=filename))
    
    @app.route('/images/<filename>')
    def get_image(filename):
    	return send_from_directory(UPLOAD_PATH,filename)
    

    SQL

    redis注册window服务
    G:\Redis>redis-server --service-install redis.windows.conf --loglevel verbose
    提示如下:则表示注册成功,可以在service.msc中查看
    [13756] 24 Sep 10:53:15.741 # Granting read/write access to ‘NT AUTHORITY\NetworkService’ on: “G:\Redis” “G:\Redis”
    [13756] 24 Sep 10:53:15.742 # Redis successfully installed as a service.

    session & cookie

    一般直接操作session.

    cookie

    百度百科:
    Cookie,有时也用其复数形式 Cookies,指某些网站为了辨别用户身份、进行 session 跟踪而储存在用户本地终端上的数据(通常经过加密)。定义于 RFC2109 和 2965 中的都已废弃,最新取代的规范是 RFC6265 [1] 。(可以叫做浏览器缓存)
    通俗的讲:
    即服务端为了辨认客户端而添加的一种标识。以键值对的形式,并不是所有的都是有用的,但是服务端由于辨识的cookie藏身于其中。解决http协议无状态特性,跟服务器混脸熟的,证明自己的。

    常用操作:
    1、添加cookie: 响应对象.set_cookie(“cookie名称”, “cookie值”, max_age=cookie存在的时间(以秒为单位)----IE8以下的浏览器不支持。可以使用expires,比较麻烦)
    2、删除cookie:响应对象.delete_cookie(cookiename)
    3、查看某个cookie:request.cookies.get(“Cookie的名称”, “default”)-------一般设置默认值,否则查询不到,报错
    4、查看所有cookie: request.cookies----------------返回的是字典对象,可以使用遍历拿数据。

    session:重要的信息,存储在这里,加密后随cookie来回跑。
    一般来说session都是存在于服务端的,少数在客户端(不安全,比如flask框架),可以通过flask-session插件,将数据放在服务端。

    它允许你在不 同请求间存储特定用户的信息。它是在 Cookies 的基础上实现的,并且对 Cookies 进行密钥签名。这意味着用户可以查看你 Cookie 的内容,但却不 能修改它,除非用户知道签名的密钥。

    如何生成强壮的密钥
    随机的问题在于很难判断什么是真随机。一个密钥应该足够随机。你的操作 系统可以基于一个密钥随机生成器来生成漂亮的随机值,这个值可以用来做 密钥:
    import os
    os.urandom(24)
    b’\xe5\xdd\x8bg\xc03\x17\xa7S\xfa\xa7u\xae\xe8\xa5\xf9\x15\x8a\xc3[\xaf\xc1\xa2?’

    使用基于 cookie 的会话需注意: Flask 会将你放进会话对象的值序列化至 Cookies。如果你发现某些值在请求之间并没有持久存在,然而确实已经启用了 Cookies,但也没有得到明确的错误信息。这时,请检查你的页面响应中的 Cookies 的大小,并与 Web 浏览器所支持的大小对比。

    session

    常用操作:
    设置密钥:
    程序实例.config[“SECRET_KEY”] = “密钥”
    添加数据:
    session[‘属性名’] = “值”
    session.pop(“session的属性名”,“default”)
    清空:
    session.clear()
    查询:
    session.get(“属性名”,default)

    flask-session使用:
    from flask_session import Session
    Session(app)

    设置session的过期时间

    有过没有设置session的有效期,那么默认就是浏览器关闭后过期,如果设置session.permanent=True,那么就会在31天后过期,如果不想在31天后过期,那么可以设置app.config[PERMANENT_SESSION_LIFETIME] = timedelta(hour=2),在两小时后过期

    一般常使用redeis保存:
    windows:启动redis服务步骤:
    1、redis-server redis.windops.conf
    2、redis-cli

    两者关系区别
    服务端保存了session的具体数据(session的属性名和对应的属性值),而sessionid(session唯一标志)“一式两份”,一份存储于服务端,另一份存储于客户端的Cookie,每次客户端发送请求时,都会携带着这个sessionid去查找服务端对应的该sessionid是否存在,如果存在,则该请求就属于这个session会话。

    闪现(flash)

    请求完成后,有时需要让用户知道状态发生了变化。这里可以使用确认消息、警告或者错
    误提醒。一个典型例子是,用户提交了有一项错误的登录表单后,服务器发回的响应重新
    渲染了登录表单,并在表单上面显示一个消息,提示用户用户名或密码错误。

    from flask import Flask, render_template, session, redirect, url_for, flash
    @app.route('/', methods=['GET', 'POST'])
    def index():
     	form = NameForm()
    	 if form.validate_on_submit():
     	old_name = session.get('name')
    	 if old_name is not None and old_name != form.name.data:
    		 flash('Looks like you have changed your name!')
     		 session['name'] = form.name.data
    		 return redirect(url_for('index'))
    	 return render_template('index.html',form = form, name = session.get('name'))
    

    蓝图(flask-blueprint )

    pip install -i https://pypi.tuna.tsqinghua.edn.cn/simple flask-blueprint

    from flask inport Blueprint
    1.py/
    blue = Blueprint("blue1",__name__)
    2.py/
    blue = Blueprint("blue2",__name__)
    
    3.py # 先导入模块1  2
    def create_app():
    	app = Flask(__name__)
    	app.register_blueprint(blue1)
    
    app = create_app()
    

    请求扩展(类似django的中间件)

    中间件

    在flask中狗子函数是使用特定的装饰器的函数,钩子函数可以在正常执行的代码中,插入一段自己想要执行的代码。(hook)
    常用钩子函数:
    1、@before_first_request 第一次请求前执行
    2、@before_request 每次请求前执行
    3、teardown_appcontext 不管是否有异常,注册的函数在每次请i去之后执行
    4、template_filter 模板的时候自定义过滤器

    @app.template_fiter
    def upper_filter(s):
    	return s.upper()
    

    5、context_processor 上下文处理器,返回的值可以在模板上下文中使用(用的多)

    @app.context_processor
    def context_processor():
    	if hasattr(g,'user')
    		return {"current_user": "xxx"}
    	return {} # 不写默认返回NONE,会报错。
    

    6、 errorhandler: 接收状态码,可以自定义返回这种状态码的响应的处理方式

    @app.errorhandler(404)
    def page_not_found(error):
    	return "this page does not exist",404
    

    注意事项:
    1、在errorhandler装饰的钩子函数下,记得要返回相应的状态码
    2、在errorhanler装饰的钩子函数下,必须要写一个参数,来接受错误的消息,如果没有参数,就会报错。
    3、使用 flask.abort可以手动的抛出响应的错误,比如开发者在发现参数不正确的时候,这可以自己手动的抛出一个400错误。

    flask信号

    信号三部曲:
    1、定义信号
    flask中的信号使用的是一个第三方插件,叫做blinker
    from blinker inport Namespace
    nameapsce = Namespace()
    2、监听信号
    3、发送信号

    flask-Restful

    简介

    为了快速构建REST API的Flask插件。他是能和现有的ORM配合的轻量级数据抽象。Flask-RESTful鼓励小型化实践

    from flask import Flask
    from flask_restful import Resource, Api
    
    app = Flask(__name__)
    api = Api(app)
    
    class HelloWorld(Resource):
    	# 重写get方法
        def get(self):
            return {"hello": "world"}
    
    api.add_resource(HelloWorld,'/')
    
    if __name__ == '__main__':
        app.run()
    

    请求分析

    响应域

    HTTP状态码

    主要有5类100类、200类、300类、400类、500类

    100-199范围内的状态码时信息消息,咋混感谢状态码都没有问题,服务端在提供关于客户端请求的详细信息
    200-299范围内的状态码时成功消息,服务器已经接收、理解和处理客户端的请求,一切正常
    300-399范围内的状态码时重定向消息,服务端同志客户端请求可以在别处处理
    400-499范围内的状态码是客户端粗错消息提示,服务端从客户端接收到一个他不理解也无法处理的请求,通常这是客户端的问题
    500-599范围内的状态码是服务端错误的消息,服务端从客户端接受到的一个请求,但是服务端尝试处理这个请求时失败了。通常这是服务器的问题。

    flask模块简介

    pip install -i https://pypi.tuna.tsqinghua.edn.cn/simple flask
    清华大学 国内镜像

    render_template: 渲染模块

    josnify: 以josn格式返回给客户端

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值