Flask_01

Flask_01

一、简介

Flask是一个Python语言编写的Web 微框架,让我们可以使用Python语言快速实现一个网站或Web服务 。

Flask是一个轻量级的框架,而Django是一个重量级的框架

Flask的轻量级表现在它的核心实现简单,不会附带很多库和功能,但同时可以让开发人员自由地去扩展这些功能

而Django的重量级表现在本身附带了很多功能实现,比如Django中有自己的DTL,ORM

“微”并不代表整个应用只能塞在一个 Python 文件内, 当然塞在单一文件内也没有问题。 “微”也不代表 Flask 功能不强或有所欠缺。 微框架中的“微”字表示 Flask 的目标是保持核心简单而又可扩展,给开发人员足够的自由。

默认情况下,Flask 不包含数据库抽象层、表单验证,或是其它任何已有多种库可以胜任的功能。然而,Flask 支持用扩展来给应用添加这些功能。

Flask 也许是“微小”的,但它已准备好在需求繁杂的生产环境中投入使用。

二、安装

首先创建一个新的虚拟环境

在虚拟环境中pip install flask 即可!

Flask 依赖两个外部库:Werkzeug 和 Jinja2 。 Werkzeug 是一个 WSGI(在 Web 应用和多种服务器之间的标准 Python 接口) 工具集。Jinja负责渲染模板。

三、快速上手

1、第一个Flask程序
from flask import Flask

app = Flask(__name__) # 初始化application实例,将成为核心对象,负责管理整个应用,处理所有请求。view, 
                      # urlConf等等都要注册于Flask对象。
    

@app.route('/')       # route()装饰器 告诉Flask 触发函数的url
def hello_world():
    #a=10/0               # 如果是调试模式开启,可以看到详细的错误信息
    return 'Hello World!' # 返回值即为响应内容,将显示在用户的浏览器上 -> Django-HttpResponse

if __name__ == '__main__':
    #app.run()  # 启动内置的WSGI服务器,启动后即可接受外界用户的访问了
    app.run(debug=True,host="localhost",port=9000)  
    #注意:开启了调试模式后,当程序出错时,可以在浏览器看到更详尽的信息

坑: Pycharm2018版本,设置debug、host、port等参数无效解决方案

  • 点击Pycharm右上角运行按钮左边的项目名称 – 下拉按钮 – Edit Configurations

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-EOtnhWBJ-1570622660276)(.\Flask-pic\Pycharm设置debug)]

2、运行
2.1 使用Pycharm

选择菜单项Run -> Run即可:
在这里插入图片描述

FLASK_APP = app.py       # FLASK_APP环境变量被用来指定如何加载应用程序。 

FLASK_ENV = development  # Flask应用运行的环境是由FLASK_ENV环境变量设置的。如果没有设置它,默认                                 为production。其他认可的环境是development。 
                         # 如果env被设置为development,flask命令会开启调试模式,并且flask run会开启                             交互式调试器(debugger)和重载器(reloading)。
    
FLASK_DEBUG = 1          # 当FLASK_ENV为development时,调试模式被开启。如果你希望单独地控制调试模                               式,使用FLASK_DEBUG可以办到:设为1表示开启调试模式,0标识禁用它。
2.2 在Terminal中运行(了解)

(TestDemo) E:\Python Web\Python-Web-Lee\09 Flask\Flask-Codes\Demo01 >

  • set FLASK_APP=app.py

  • set FLASK_ENV=development

  • python -m flask run --port=9999

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-36m4kokw-1570622660280)(.\Flask-pic\1532864128100.png)]

四、路由URLConf

在Flask程序中,使用route()装饰器把一个函数绑定到对应的 URL 上 。

1、基本配置
@app.route('/')            # localhost:5000/
def hello_world():         # 不需要加request参数
    return 'Hello World!'


@app.route('/index1/')     # localhost:5000/index1/
def index1():
    return "URLConf-1"


@app.route('/index2/<name>')  # 命名路径  # localhost:5000/index2/Tom
def index2(name):
    return name
2、转换器

对于命名路径,可以使用转换器,限定内容:

2.1 Flask提供的默认转换器
#: the default converter mapping for the map.   
DEFAULT_CONVERTERS = {
    'default':          UnicodeConverter,
    'string':           UnicodeConverter,
    'any':              AnyConverter,
    'path':             PathConverter,
    'int':              IntegerConverter,
    'float':            FloatConverter,
    'uuid':             UUIDConverter,
}

示例:

@app.route('/index3/<string:name>')      # string 可以不用定义,默认就是接收字符串
def index3(name):
    return name

@app.route('/index4/<int:age>')          # 只接受整数,age参数类型为int,不再是默认的string
def index4(age):
    return str(age)

@app.route('/index5/<path:name>')        # /d/a/b/c/d/ 可以访问,name="/a/b/c/d" 
def index5(name):
    return name

@app.route("/index6/<any('Mr_lee','Tom'):name>")   # name="Mr_lee"或"Tom"
def index6(name):
    return name

@app.route("/index7/<float:salary>")   # salary为float数
def index7(salary):
    return str(salary)

@app.route("/getUUID/")
def index88():
    return redirect("/index8/"+str(uuid.uuid4())+"/")

@app.route("/index8/<uuid:uid>/")         # /index8/b9630970-27af-4da9-929b-20daaf2af959可以访问
def index8(uid):
    return str(uid)
2.2 自定义正则转换器
# 1. 自定义转换器类
class RegexConverter(BaseConverter): # 自定义类,继承BaseConverter(所有转换器的父类)
    def __init__(self,map,*args):    # args=转换器的参数
        self.map = map
        self.regex = args[0]         # BaseConberter中的属性regex

# 2. 注册转换器          名称(键)      实现类(值)
app.url_map.converters['regex'] = RegexConverter 

# 3. 使用转换器
@app.route("/index9/<regex('\d{2}'):age>/")  # \d{2} 会参数给自定义类的args参数
def index9(age):
    return str(age)

五、跳转

1、跳转到Template
@app.route("/template/")
def template():
    return render_template("index.html")   # 转发到index.html (模板根目录是templates)
2、跳转到view(重定向)
@app.route("/index9/")
def index9():
    return "被重定向的页面"

@app.route("/index10/")
def index10():
    url = url_for("index9")   # url_for相当于reverse反向解析, url_for(“view函数名”)
    print(url)
    return redirect(url)      # redirect(url) 重定向

# 在template中使用 <a href="{{ url_for('index9') }}">index9</a> 

重定向传参:

#命名路径接收参数
@app.route("/index9/<age>/")
def index9(age):
    print(age)
    return "被重定向的页面"

# request接收参数
@app.route("/index99/")
def index99():
    request.args.get("age")
    return "被重定向的页面"

@app.route("/index10/")
def index10():
    url = url_for("index9",age=20)   # url_for相当于reverse反向解析, url_for(“view函数名”)
    print(url)
    return redirect(url)

六、request访问请求参数

1、Get请求参数
from flask import request                       # 全局request对象
request.args.get("id")                          # 获取id参数,没值报None
request.args["id"]                              # 获取id参数,没值报错
request.args.getlist("id")                      # 返回list
2、Post请求参数
from flask import request
request.form.get("id")             # 获取id参数,没值报None
request.form["id"]                 # 获取id参数,没值报错
request.form.getlist("id")         # 返回list 

注意:View函数默认直接收Get请求,如果要发送post,需要设置:

@app.route("/index11/",methods=['get','post'])
def postParam():
    name = request.form.get('userName')
    password = request.form.get('password')
    print(name,password)
    return "post参数接收"

七、模板渲染

1、简介

模板其实是一个包含响应文本的文件,其中用占位符(模板变量 {{name}} )表示动态部分内容,告诉模板引擎其具体的值需要从使用的数据中获取,使用真实值替换变量,再返回最终得到的字符串,这个过程称为“渲染”。 Flask是使用 Jinja2 这个模板引擎来渲染模板 。

Jinja2:是 Python 下一个被广泛应用的模板引擎,是由Python实现的模板语言,他的设计思想来源于 Django 的模板引擎,并扩展了其语法和一系列强大的功能,jinja2是Flask内置的模板语言。

模板语言:是一种被设计来自动生成文档的简单文本格式,在模板语言中,一般都会把一些变量传给模板,替换模板的特定位置上预先定义好的占位变量名。

使用模板的好处:

  • 视图函数只负责业务逻辑和数据处理(业务逻辑方面)
  • 而模板则取到视图函数的数据结果进行展示(视图展示方面)
  • 代码结构清晰,耦合度低 。
2、转发模板
@app.route("/index12/")
def index12():
    return render_template('index.html')
3、模板变量

在view中向模板中传递数据,动态生成页面内容 (从view中传数据到模板文件中)

3.1 view中传值
@app.route("/index12/")
def index12():
    return render_template('index.html',name="Mr_lee",age=18,birthday=datetime.datetime.now(),data={"hobby":['basketball','football'],"height":180,"weight":0})
3.2 template中取值
{{ name }} <br>
{{ age }} <br>
{{ data }} <br>
{{ data.height }}cm
{{ data.hobby[0] }} -- {{ data.hobby.0 }} <br>
4、过滤器
4.1 内置过滤器
{{ name | upper }}
{{ name | length }}
{{ name | lower }}
{{ name | trim }}   <!-- 掐头去尾,去掉字符串开头和结尾的空格 -->    

{{ abc | default("abc不存在") }}               <!-- abc不存在时,显示default中的内容 --> 
{{ data.weight | default("weight为0",true) }}  <!-- data.weight为None0、false、""--> 
4.2 自定义过滤器
# 1. 自定义过滤器函数
def dateformat(value,format="%Y-%m-%d"):   # format默认值可选  
    return value.strftime(format)

# 2. 在filters中注册自定义过滤器
app.jinja_env.filters['dateformat'] = dateformat 

# 3. template中使用自定义过滤器
{{ birth | dateformat("%Y-%m-%d") }}
5、测试器

is 测试器 进行各种判断

5.1 是否定义
测试器:defined=是否定义
{% if birthday is defined %} 
	birthday is there
{% endif %}
{% if birthday %}
	birthday is there2
{% endif %}
5.2 是否可以整除
测试器:divisibleby=是否可以整除
{% if (data.list.0 + 1) is divisibleby(2) %}
	{{ data.list.0 }} % 2 == 0
{% endif %}
{% if not data.list.0 + 1 is divisibleby(2) %}
	{{ data.list.0 }}  not % 2
{% endif %}
5.3 奇偶数
测试器:even/odd=是否是偶数/奇数
{% if not data.list.0 + 1 is even %} {# odd 是奇数测试#}
	1+1 是偶数
{% endif %}
5.4 大小写
测试器:lower/upper=是否是小写/大写字符
{% if data.name is lower %} {# upper 是大写#}
	name is lower
{% endif %}
6、运算
{{ data.list.0 + 1 }}
{{ data.list.1 - 1 }}
{{ data.list[0] * 10 }}
{{ data.list[0] / 2 }}
{{ (data.list[0] + 1) % 2 }}

{{ data.list[0]>1}}
{{ data.list[0]==1}}
{{ data.list[0]<=1}}
{{ data.list[0]!=1}}

{{ data.list[0]==1 and 1==2 or 1==1}}
{{ data.list[0]==1 and 1==2 or not 1==1}}

{{ "hilo" ~ data.name ~ "!!" }} {# 字符串拼接 #}
7、标签
7.1 逻辑判断

逻辑判断中的0、None、“”、[]、没值 都做为False

{% if data.list | length < 10 %}
	lt 10
{% endif %}

{% if age + 1 < 10 %}
	lt 10
{% endif %}

{% if age + 1 > 17 and name|trim=="Mr_lee" and name is lower %}
	.....
{% endif %}

{% if data.name|trim == "Mr_lee" %}
	hilo,Mr_lee
{% endif %}

{% if data.name == "Mr_lee" %}
	hilo,Mr_lee2
{% elif not data.name|trim=="Mr_lee" %}
	hilo,Mr_lee3
{% else %}
	hilo,Mr_lee4
{% endif %}
7.2 循环
{% for user in users %}
  <li>{{ user }}</li>
{% endfor %}

{% for user in users %}
    {% if loop.index is odd %}
    	<li><span style="color:red">{{ user }}</span></li>
    {% elif loop.index is even %}
    	<li><span style="color:green">{{ user }}</span></li>
    {% endif %}
{% endfor %}

{% for key, value in my_dict.items() %}
    {{ key }}
    {{ value }}
{% endfor %}
range()--模板的全局函数 range(4) == range(0,4) == range(0,4,1) 最后一个1表示增量

{% for number in range(10) %}
    <a href="xxxx?num={{number}}">{{number}}</a>
{% endfor %}

八、模板继承

1、继承extends
  • 在多个模板文件中,会有相同的部分,造成模板代码冗余
  • 通过父模板的定义,抽取出所有的冗余部分。
  • 利于管理和维护
base.html
...
<body>
    <div style="background-color:lavender;margin-bottom: 100px">
        欢迎你,{{ user.name }}
    </div>
    {% block content%}
        
    {% endblock %}
    <div style="font-size: 12px;color:#999;margin:0 auto;text-align: center;padding:20px 0">
        Copyright © 2013-2018
        <strong><a href="#" target="_blank">百知</a></strong>&nbsp;
        <strong><a href="#" target="_blank">baizhi.com</a></strong> All Rights Reserved. 
    </div>
</body>
sub.html

{% extends "base.html" %}

{% block content %}  {#-- 覆写父模板block --#}
    <div style="height: 100px;background-color: #999999">
        这是子类模板自己的内容
    </div>
{% endblock %}
2、包含include
  • 可以将一个大页面先做好布局,然后布局内的内容可以单独定义一个模板文件,然后再做包含
  • 便于管理复杂的模板文件
  • 效果和ajax中的load方法相似
...
<body>
    <div style="float: left;height: 300px;width:200px">
        {% include "part1.html" %}
    </div>
    <div style="float: left;height: 300px;width:200px">
        {% include "part2.html" %}
    </div>
</body>
...
part1.html:可以是一个完整的html,也可以是html片段
<div style="width: 100px;height: 300px;background-color: red">{{ birth }}</div>

九、全局错误页面

@app.errorhandler(404) #404错误会自动转到此view,这样就单独定制了404页面
def not_found(e):
	return render_template("404.html")

@app.errorhandler(500) #500错误会自动转到此view,这样就单独定制了500页面(非调试模式下有效)
def not_found(e):
	return render_template("500.html")
  {% include "part1.html" %}
</div>
<div style="float: left;height: 300px;width:200px">
    {% include "part2.html" %}
</div>
... ```
part1.html:可以是一个完整的html,也可以是html片段
<div style="width: 100px;height: 300px;background-color: red">{{ birth }}</div>

九、全局错误页面

@app.errorhandler(404) #404错误会自动转到此view,这样就单独定制了404页面
def not_found(e):
	return render_template("404.html")

@app.errorhandler(500) #500错误会自动转到此view,这样就单独定制了500页面(非调试模式下有效)
def not_found(e):
	return render_template("500.html")
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
这个错误怎么解决:192.168.34.71 - - [14/Jan/2023 22:41:01] "GET /get_nb2_ip/ HTTP/1.1" 500 - Traceback (most recent call last): File "/usr/local/lib/python3.8/dist-packages/flask/app.py", line 2548, in __call__ return self.wsgi_app(environ, start_response) File "/usr/local/lib/python3.8/dist-packages/flask/app.py", line 2528, in wsgi_app response = self.handle_exception(e) File "/usr/local/lib/python3.8/dist-packages/flask_cors/extension.py", line 165, in wrapped_function return cors_after_request(app.make_response(f(*args, **kwargs))) File "/usr/local/lib/python3.8/dist-packages/flask_cors/extension.py", line 165, in wrapped_function return cors_after_request(app.make_response(f(*args, **kwargs))) File "/usr/local/lib/python3.8/dist-packages/flask/app.py", line 2525, in wsgi_app response = self.full_dispatch_request() File "/usr/local/lib/python3.8/dist-packages/flask/app.py", line 1823, in full_dispatch_request return self.finalize_request(rv) File "/usr/local/lib/python3.8/dist-packages/flask/app.py", line 1842, in finalize_request response = self.make_response(rv) File "/usr/local/lib/python3.8/dist-packages/flask/app.py", line 2170, in make_response raise TypeError( TypeError: The view function did not return a valid response. The return type must be a string, dict, list, tuple with headers or status, Response instance, or WSGI callable, but it was a Response.代码是这个:@app.route('/get_nb2_ip/') def get_nb2_ip(): #curl -i --basic -u admin:public -X GET "http://192.168.34.131:8081/api/v4/clients?_page=1&_limit=10" response = requests.get('http:192.168.34.131:8081/api/v4/clients?_page=1&_limit=10', auth=('admin', 'public')) return response
最新发布
02-06

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值