flask框架

简介:

使用 Python 编写的轻量级 Web 应用框架。其 WSGI 工具箱采用 Werkzeug ,模板引擎则使用 Jinja2 

werkzeug报的底层用法:

# 引用werkzurg的功能模块
from werkzeug.wrappers import Request,Response
from werkzeug.serving import run_simple
# 底层的用法
def run(environ,start_response):
    return [b'abcdefg'] 
if __name__ == '__main__':
    run_simple('localhost',4000,run) # 监听端口并执行run函数
    # 另一种用法
@Response.application
def hello(request):
    return Response('Hello World!')
    '''
        return到底返回到客户端什么内容?
        1、状态码:status code 200,301,404,返回一个响应的客户端的状态码;
        2、content-type:告诉客户端用什么方式解析返回的值;
        3、其他的返回头信息。
    '''
if __name__ == __main__:
    run_simple('localhost',4000,hello)

基本模式:

Flask的基本模式为在程序里将一个视图函数分配给一个URL,每当用户访问这个URL时,系统就会执行给该URL分配好的视图函数,获取函数的返回值并将其显示到浏览器上,工作原理如图:

FLASK主要部分:

1.应用程序对象:应用程序对象是Flask应用程序的核心对象。它是一个Flask类的实例。应用程序对象是用于创建Web应用程序的主要接口。

2.上下文:

Flask框架中有两种上下文:应用程序上下文和请求上下文。

应用程序上下文:为应用程序提供了一个全局上下文

请求上下文:为每个请求提供了一个上下文。

3.路由:路由是Flask应用程序中的URL映射。它指定了URL与视图函数之间的关系。

4.视图函数:视图函数是Flask应用程序中处理请求的函数。它们使用装饰器将路由绑定到函数上。

5.模板:模板是Flask应用程序中用于渲染HTML页面的文件。它们使用Jinja2模板引擎进行渲染

6.表单:表单是Flask应用程序中用于收集用户输入数据的HTML表单。它们使用WTForms库进行验证和处理。

常见的应用结构:

myapp/

__init__.py :Flask应用程序的入口文件

views.py:包含了应用程序的视图函数

models.py:包含了应用程序的模型类

templates/:包含了应用程序的HTML模板文件

index.html:包含了应用程序的静态文件,如CSS和JavaScript文件

about.html

static/

css/

style.css

js/

script.js

路由(静态参数):

路由是用于将URL映射到视图函数的机制,Flask提供了一个route()装饰器来定义路由。

示例:

from flask import Flask

app = Flask(__name__)

@app.route('/')

def index():

return 'Hello World!'

含义:定义了一个根路由('/')和一个名为index()的视图函数,当用户访问根URL时,Flask将调用index()函数并返回'Hello World!'字符串

路由(动态参数):

示例:

@app.route('/user/<username>')

def user_profile(username):

return 'User: %s' % username

含义:定义了一个user_profile()视图函数,并将其绑定到/user/<username>路由上,当用户访问URL时,Flask将提取URL中的username参数,并将其传递给user_profile()函数

模板:

模板是用于渲染HTML页面的文件。Flask使用Jinja2模板引擎来渲染模板

<!DOCTYPE html>
<html>
<head>
<title>{{ title }}</title>
</head>
<body>
<h1>{{ heading }}</h1>
<p>{{ content }}</p>
</body>
</html>
from flask import Flask, render_template

app = Flask(__name__)

@app.route('/')

def index():

return render_template('index.html', title='Home', heading='Welcome to my website', content='This is the home page.')

含义:定义了一个index()视图函数,并使用render_template()函数渲染index.html模板。我们还将title、heading和content变量传递给模板,以便在模板中渲染。

表单:

表单是用于收集用户输入数据的HTML表单,Flask使用WTForms库来验证和处理表单数据。

示例:

from flask_wtf import FlaskForm

from wtforms import StringField, SubmitField

from wtforms.validators import DataRequired

class ContactForm(FlaskForm):

name = StringField('Name', validators=[DataRequired()])

email = StringField('Email', validators=[DataRequired()])

message = StringField('Message', validators=[DataRequired()])

submit = SubmitField('Send')

含义:定义了一个ContactForm类,使用StringField和SubmitField字段定义表单字段,使用DataRequired验证器来验证字段是否为空

视图函数:

使用form属性来访问表单数据

from flask import Flask, render_template, request

from forms import ContactForm

app = Flask(__name__)

app.secret_key = 'secret'

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

def contact():

form = ContactForm()

if form.validate_on_submit():

name = form.name.data

email = form.email.data

message = form.message.data

# send email

flash('Your message has beensent!')

return redirect(url_for('contact'))

return render_template('contact.html', form=form)

含义:定义了一个contact()视图函数,使用ContactForm类定义一个表单。在视图函数中,先创建了一个表单实例,并将其传递给contact.html模板。如果表单已经被提交并且通过了验证,将从表单中提取数据,并执行其他操作,例如发送电子邮件。最后,我们使用flash()函数向用户显示一条消息,并使用redirect()函数将用户重定向到联系页面

数据库:

常见的数据库扩展:

1.Flask-SQLAlchemy:这是一个SQLAlchemy的Flask扩展,它提供了ORM(对象关系映射)功能。

2.Flask-MongoAlchemy:这是一个MongoAlchemy的Flask扩展,它提供了MongoDB的ORM功能。

3.Flask-PyMongo:这是一个PyMongo的Flask扩展,它提供了MongoDB的Python驱动程序。

示例:

Flask-SQLAlchemy扩展的示例

from flask import Flask

from flask_sqlalchemy import SQLAlchemy

app = Flask(__name__)

app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///test.db'

db = SQLAlchemy(app)

class User(db.Model):

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

username = db.Column(db.String(50), unique=True, nullable=False)

email = db.Column(db.String(50), unique=True, nullable=False)

def __repr__(self):

return '<User %r>' % self.username

含义:定义了一个User类,使用db.Column()函数定义了类的属性。定义了__repr__()方法,它用于在控制台中显示User对象的字符串表示形式。在视图函数中,可以使用db.session来访问数据库。

示例:

from flask import Flask, render_template

from models import db, User

app = Flask(__name__)

app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///test.db'

db.init_app(app)

@app.route('/')

def index():

users = User.query.all()

return render_template('index.html', users=users)

含义:将User类从models.py文件中导入,使用User.query.all()方法获取所有用户。将用户列表传递给index.html模板,以便在模板中渲染。

简单的登录:

from flask import Flask as fk , request,render_template as render,redirect,session,make_response
app = fk(__name__)
app.secret_key = 'abckd' # 设置session 的加密值
@app.route('/',methods=['GET','POST'])
def index():
    if request.method == 'POST':
        user = request.form.get('user')
        pwd = request.form['pwd']
        if user == 'admin' and pwd == '123':
            print(user,pwd)
            return '登录成功!'
    return render('index.html',h2='你好')
    # home.add_url_rule('/',view_func=index) #第二种路由的声明方式,必须已“/”开头
if __name__ == '__main__':
    app.run(debug=True,host='192.168.0.11',port=5000) 
'''
执行werkzurg中的run_simple('localhost',4000,hello)
这里只是socket进行了请求监听,当浏览器发起请求后,执行内部的__call__()方法。
'''

 Threading.local 多线程:

线程的作用:

为每个线程创建一个独立的空间,使得线程对自己空间中的数据进行操作(数据隔离)

示例:

import threading
from threading import local
local_obj = local() # 实例化local对象
def task(i):
    local_obj.xxx = i # 为local对象设置一个参数
    print(local_obj.xxx,i) # 获取local对象中的参数
    # threading.get_ident() 获取线程的唯一标示
    print(threading.get_ident(),i)
for i in range(10):
    t = threading.Thread(target=task,args(i,)) # 创建线程
    t.start() # 开始执行线程

 根据字典自定义类似Threading.localz:

import threading
import greenlet # 获取协程信息
DIC = {}
def task(i):
# 获取协成的唯一标记
# indent = greenlet.getcurrent()
# treading.get_ident() 获取线程的唯一标记
    indent = treading.get_ident()
    if indent in DIC:
        DIC[indent]['xxx'] = i
    else:
        DIC[indent] = {'xxx':i}
    print(DIC[index][xxx],i) # 打印字典中的参数
for i in range(10):
    t = threading.Thread(target=task,args=(i,)) # 创建线程
    t.start() # 开始执行线程

 自定义升级版Threading.localz:

此版本中协程与线程可以完全的兼容,完成对请求的数据隔离。 为什么需要给线程和协程数据进行隔离? 在多个请求的时候,由于每个请求的信息不相同,所以需要对不同的请求信息进行分类管理(数据隔离),从而防止数据混乱; 这样在需要使用视图函数取得用户请求信息的时候,才能根据不同的信息进行取值和修改。

 

import threading
import time
 
try:
    import greenlet # 获取协程信息
    get_indent = greenlet.getcurrent
except Exception as e:
    get_indent = threading.get_ident
class local(object):
# DIC={}
    def __init__(self):
   # pass
        object.__setattr__(self,'DIC',{}) # 通过父类的方法设置类属性
    def __getattr__(self,item):
        indent = get_indent()
        if indent in self.DIC:
            return self.DIC[indent].get(item)
        else:
            return None
    
    def __setattr__(self,key,value):
        indent = get_indent()
        if indent in self.DIC:
            self.DIC[indent][key] = value
        else:
            self.DIC[indent]= {key:value}
    
    obj = local() # 类在实例化的时候运行__init__()方法
  '''
    obj.xx # 对象.方法的时候运行__getattr__()方法,并且把xx当参数传入
    obj.xx = 123 # 对象.方法赋值的时候运行__setattr__()方法,并且把xx和123当参数传入
  '''
    def task(i):
        obj.xxx = i
        time.sleep(2)
        print(obj.xxx,i)
    for i in range(10):
        t = threading.Thread(target=task,args=(i,)) # 创建线程
        t.start() # 开始执行线程

Flask 的基本执行流程:

封装 requestContext 对象, full_dispatch_request(视图函数 执行), response返回
从app.run() 开始 -->>
Flask的__call__方法-->>
wsgi_app (封装RequestContext(request,session)对象到 localstack) -->>
full_dispatch_request(视图函数 执行) -->>
执行扩展(before_request) ,触发信号 -->>
获取response -->>
pop reqeust、session -- >>
结束

 Flask 源码执行顺序:

(1)threading local 和 flask的自定义local对象 
        - 基于本地线程 可以实现线程隔离。
(2)请求到来
        封装  ctx = RequestContext(request,session)
             ctx -- 放入 Local __storage__ { 'id':{stack:[ctx]} }
(3)执行视图
        导入 request
        print(reqeust) -- >> localproxy __str__
        reqeust.method -- >> localproxy __getattr__
        reqeust + 1 -- >> localproxy __add__    
        调用_lookup_req_object函数,去local中的ctx中获取reqeust session
(4)请求结束
        ctx.auto_pop
        ctx 从 local 中移除

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值