#encoding=utf-8
"""
1、创建web服务器实例:app = Flask(__name__,template_folder,static_folder)
(1)__name__:内置方法,是模块的名称或者包的名称,确定应用的路径
A、默认的值直接执行当前文件:__name__="__main__"(直接执行文件|被导入执行)
B、修改被导入文件的相对路径:__name__="文件的相对路径"(指执行的优先级)
(2)template_folder:指定前端页面的存放路径
A、默认网页html文件的目录,在当前文件的同级目录的templates目录下
B、通过template_folder="文件路径/templates"可以配置html网页的查找目录
(3)static_folder:指定静态文件的存放路径
A、默认静态文件的目录,在当前文件的同目录下的static目录下,可以通过配置项更改模板文件和静态文件的存放目录
B、可以通过static_folder="文件路径/static"可以配置静态文件的查找目录
(4)app就是一个程序实例
A、客户端(一般是浏览器)将请求发送给服务端Web服务器
B、Web服务器再把请求发给Flask实例
(5)Flask的配置文件
A、app属性的方式:app.debug=True
B、app.config字典形式:app.config["DEBUG"] =True
C、py文件作为配置文件,settings.py中写配置代码:app.config.from_pyfile("setting.py")
D、以类的形式,推荐使用:app.config.from_object("settingobj.TestConfig")
>> settingsobj是独立的py文件,在文件中以类的形式定义配置,需要使用配置时直接settingobj.类名就可以
class Config:
DEBUG = False
class ProductConfig(Config):
pass
class TestConfig(Config):
DEBUG = True
(5)更多参数参考__doc__:print(Flask.__doc__)
2、Jinja2模板技术
(1)直接在视图中定义HTML结构数据是十分困难的,可以使用外部的HTML文件加载来渲染页面
(2)jinja2模块给flask提供了加载html页面的能力,可以使用jianjia2的语法来直接使用已经写好的HTML页面
(3)render_template方法: 自动的加载当前路径下的templates下的同名html,然后将html返回到浏览器
(4)可以将视图当中的数据渲染到前台页面上,少量数据可以用键=值的形式进行传参到前端
(5)大量/较多数据时,可以使用**locals()的方式,一次性将所有数据传送到前端页面,Locals是对局部变量整合的字典
(6)模板引擎负责MVC中的V(view视图)部分
A、Flask本身不带模板系统,默认使用Python开发的Jinja2模板引擎
B、Jinja2是Django模板系统的仿制品,功能却更为完善
C、现Django可以舍弃自己的模板系统,可以采用Jinja2系统
(7)前端静态文件
A、服务器上将前端资源分为静态资源和动态资源,全栈开发中css、js、img等非html内容看作静态内容
B、可以在创建web服务器实例中设置HTML文件存储目录和静态文件存储目录
C、静态资源:本身内容不会发生修改,服务器会将静态资源放到某个位置上,直接加载
D、动态资源:根据不同交互情况发生修改(数据库数据)
(8)页面加载
A、返回数据模块:from flask import render_template
B、在main文件同级目录创建templates目录,编写html文件
C、默认查找加载当前目录/指定目录下的templates目录中的html
D、导入使用render_template方法,加载返回html页面
E、函数处理数据,将加载的内容通过模板语法渲染到页面上
(9)数据渲染:把视图函数当中的数据传递到html页面上
A、数据以字典方式返回:return render_template("html文件",name="杜迅")
B、数据以全部形式返回:return render_template("html文件",**locals())
3、静态加载
(1)静态资源一般不放在数据库中,而是直接放在服务器上
(2)通常在数据库当中保存的是图片/其他静态资源的地址,而资源本身放在服务器上,以便减小数据库的存储空间
(3)当前HTML页面中的所有数据都是直接写在页面内部的,若想加入图片/外部样式文件是加载不上的,需要配置static静态资源
(4)静态文件需要放在默认的静态位置(配置静态资源路径下的static目录),在html中默认使用/static/为资源的根路径
(5)开发过程中,一般后端工程师会直接使用前端写好了的静态HTML页面,后端工程师需要将静态资源内容加载到项目当中
(6)静态加载步骤
A、静态准备:在项目目录下创建static来存放静态文件(默认),创建templates来存放模板文件(默认)
B、静态文件:将已经开发好的静态文件(非html)复制到static
C、开发页面:将要开发的页面放入到templates目录当中
D、脚本创建:创建flask脚本,使用render_templates加载页面(加载开发页面)
E、修改路径:页面的静态资源地址和服务器需要的路由地址不相符,需要进行修改,将所有静态资源地址替换为指定路由路径
F、a链接:所有的href路由指向是错误的,需要进行修改,只需按照访问地址,使用恰当的路由替换即可
4、JinJa2模板使用
(1)模板基础
A、直接修改HTML页面时,会出现大量的重复性的加载引入,会出现代码冗余、开发效率低等问题,可以将各个页面共性的部分抽离出来,单独编写模板
B、模板页是所有页面都要使用的,可以使用模板继承的方式来使各个页面都可以使用,只需修改模板页,所有继承的页面也会随之改变
C、只使用页面的继承会抹杀掉各个页面独有的部分,使得所有的页面都是一个模样,这时需要使用block的方式为个性修改留下空间
D、查看HTML页面,复制一个页面作为base基础模板
E、查看分析网页共性和个性的部分,共性部分不发生改动,个性部分使用{% block %} {% endblock %}定义
F、可以使用{% extends "模板名称.html" %}继承基础模板
G、可以使用{% include "模板名称.html" %}导入整个页面,将需要的页面拉到当前页面的指定位置
H、修改个性:直接在个性页面的部分使用block方法,个性部分会覆盖继承的原数据
(2)继承与加载
A、定义一个模板页base,将网页共性的部分保留下来,在需要修改部分定义块标签block
B、其他页面继承模板页,只需要使用块标签修改属于自己的部分就可以了
C、块标签内部可以有默认值,共性的部分如果发生修改,只需要修改base页面
D、定义块: {% block 块名 %}"默认值"{% endblock %}
F、继承模板,可以修改块标签部分:{% extends "模板块名称" %}
G、加载模板,直接拉取渲染页面:{% include "html文件" %}
H、模板继承可以使每个页面的特定元素(如页头、导航和页尾) 保持一致
(3)变量{{}}:可以接收视图函数传递过来的对象并调用方法
A、{{变量.upper()}}:字符串值所有英文字母大写
B、{{变量.索引}}:获取字符串对应索引的字符
C、{{变量.split("数据")}}:按照给定数据分割
D、{{变量.replace('数据1','数据2')}}:将变量中的数据1替换成数据2
(4)if标签:{% if 条件1 %}-{% elif 条件2 %}-{% else %}-{% endif %}
(5)for标签:{% for 变量 in 可迭代对象 %}-{% else %}-{% endfor %}
(6)loop变量:内置在for-loop循环中
A、loop.index:返回循环对象从1开始的索引
B、loop.index0:返回循环对象从0开始的索引
C、loop.first:判断是否第一个
D、loop.last:判断是否是最后一个
E、loop.length:给出长度
(7)过滤器:将视图传递的数据,进行二次处理 {{ 变量|方法(upper、lower、safe) }}
A、upper过滤,字母全部大写:{{ arg|upper }}
B、lower过滤,字母全部小写:{{ arg|lower }}
C、capitalize过滤,首字母大写:{{ arg|capitalize }}
D、title过滤,标题形式:{{ arg|title }}
E、replace过滤,替换数据:{{ arg|replace("A","d") }}
F、round过滤,四舍五入:{{ arg|round|类型int }}
G、safe过滤,安全展示:{{ arg|safe }}
H、过滤器当中有个性的过滤器 safe取消了前端代码转义:{{ script|safe }}
>> 转义: 模版认为视图传递的标签语言不安全,会将这部分内容进行转义为普通字符串
>> 安全策略:最影响网站安全的手段有一种注入攻击
>> 注入攻击:前端注入,数据库注入
>> Flask本身携带反前端注入安全策略,使用safe过滤器可以解除安全策略
C、过滤器在开发当中通常用于自定义
>> 定义用于指定过滤规则的函数
>> 全局-添加过滤规则到app中:app.add_template_filter(函数名,"规则名")
>> 装饰器-添加过滤规则到app中(在自定义函数上):@app.template_filter('规则名')
>> 前端使用:{{ 变量名|规则名 }}
(8)自动转义默认开启
A、信任某个变量,且确定是安全的html,可以使用Markup类标记为安全的,或在模板中使用|safe过滤器
B、from markupsafe import Markup
C、Markup(f'<strong>Hello <blink>hacker</blink>!</strong>')
D、Markup.escape('<blink>hacker</blink>')
E、Markup('<em>Marked up</em> &raquo; HTML').striptags()
"""
import os
import random
from flask import Flask, render_template
from flask import Markup
basic = "F:/MyProject"
app = Flask(__name__)
def ff(arg, b):
return Markup(arg + b)
# 自定义过滤器-单参数
def myadd(number):
number = str(number)
if len(number)!=11:
number = None
elif type(eval(number))!=int:
number = None
else:
number = number[:3]+"****"+number[-4:]
return number
# 模板过滤器:自定义函数名,前端传递数据(过滤器名)
app.add_template_filter(myadd, "MyAdd")
# 自定义过滤器 - 多参数
def mymoney(num1, num2, num3):
return num1 + num2 + num3
# 模板过滤器:自定义函数名,前端传递数据(过滤器名)
app.add_template_filter(mymoney, "MyMoney")
# 自定义过滤器规则(替换敏感词为**),注意在全局添加过滤filter
def filter_name(args):
if len(args) == 0:
obj = args.replace("傻逼", "**")
else:
username = args[0]
gender = args[1]
if gender == "男":
obj = username[0] + "先生"
elif gender == "女":
obj = username[0] + "女士"
else:
obj = username
return obj
# 添加过滤器,调用name函数,指定过滤器规则NAME
app.add_template_filter(filter_name, "SENSITIVE")
# 定义加密号码的过滤器(使用装饰器)
@app.template_filter('ENCRYPT')
def filter_number(obj):
obj = str(obj)
if len(obj) == 11:
return f"{obj[:3]}****{obj[7:]}"
else:
return '号码有问题~'
# 定义一个模板页,通过include方法可以将这个页面引用加载到新页面中
@app.route('/template/include')
def include():
# 加载指定目录下的templates目录中的html,使用render_template将数据返回
return render_template("include.html")
# 定义一个模板页,通过extends方法可以对页面中私有部分进行修改
@app.route('/template/extends')
def extends():
# 加载指定目录下的templates目录中的html,使用render_template将数据返回
return render_template("extends.html")
@app.route("/")
def index():
a = 123
dct = {
1: {"name": "TT", "long": 160, "颜值": 50},
2: {"name": "KK", "long": 170, "颜值": 60},
3: {"name": "GG", "long": 190, "颜值": 80}
}
html = "<h1>TT is sb</h1>"
# 前端调用:{{ num | MyAdd }}
# 前端调用:{{ num | MyMoney(20,10) }}
return render_template("index1.html", num=a, user_dic=dct, htm=html, ff=ff)
# 可以接收视图函数传递过来的对象并调用方法将数据进行处理
@app.route('/template/label')
def label():
init = 'init_Info'
img = "资料/"+random.choice([file for file in os.listdir(f"{basic}/static/imgs/资料")])
user = "哈哈"
pswd = "xun961031"
status = "管理员"
lst = ["loop首位", "Java", "PHP", "Python", "JavaScript", "loop末尾位"]
detail = "detail_Info"
script = "<script>window.location.href = '#'</script>"
words = "他是个大sb~"
number = 18810629376
books = [
{"name": "《西游记》", "type": "必读", "author": "朋朋", "public": "延边出版社"},
{"name": "《奥特曼战矮人》", "type": "选读", "author": "森森", "public": "新华"},
{"name": "《卖书的葫芦》", "type": "必读", "author": "迅迅", "public": "西安"},
{"name": "《天线宝宝》", "type": "选读", "author": "安安", "public": "清华大学"},
{"name": "《桃花大战菊花》", "type": "必读", "author": "框框", "public": "中公"}
]
# 数据以全部形式返回:return render_template("html文件",**locals())
# locals():将局部函数内所有参数,按键=值的方式,将所有参数添加到一个字典中进行打包传递
# **locals():是对局部变量整合的一个字典,传递时需要**打包
return render_template("label.html", **locals())
@app.route('/args/<func>')
def args_demo(func):
os.system(f'python {basic}//test//client.py {func}')
data = f'执行{func}函数功能,已完成{func.split("_")[0]}请求~'
return render_template('base1.html', **locals())
if __name__ == '__main__':
# 模板过滤器:自定义函数名,前端传递数据(过滤器名)
app.add_template_filter(myadd, "MyAdd")
# 模板过滤器:自定义函数名,前端传递数据(过滤器名)
app.add_template_filter(mymoney, "MyMoney")
# 添加过滤器,调用name函数,指定过滤器规则NAME
app.add_template_filter(filter_name, "SENSITIVE")
def run(self):
app.run(
# host:主机地址
host="localhost",
# port:访问端口
port=80,
# debug:调试模式,测试环境True,生产环境Fasle
debug=True,
# use_reloader:自动重启
use_reloader=True
)