作者简介:大家好,我是爱敲代码的小王,CSDN博客博主,Python小白
系列专栏:python入门到实战、Python爬虫开发、Python办公自动化、Python数据分析、Python前后端开发
如果文章知识点有错误的地方,请指正!和大家一起学习,一起进步
如果感觉博主的文章还不错的话,请三连支持一下博主哦
博主正在努力完成2023计划中:以梦为马,扬帆起航,2023追梦人
python入门到实战专栏:从入门到实战
Python爬虫开发专栏:从入门到实战
Python办公自动化专栏:从入门到实战
Python数据分析专栏:从入门到实战
Python前后端开发专栏:从入门到实战
模板继承
继承模板实战
装饰器
蓝图介绍
单文件蓝图
蓝图的目录结构
蓝图中模版文件
蓝图中静态文件
蓝图url_for函数
子域名实现
为什么需要模版继承
模版继承可以把一些公用的代码单独抽取出来放到一个父模板中以后子模板直接继承就可以使用了。这样可以重复的利用代码,并且以后修改起来也比较方便
模版继承语法
使用 extends 语句,来指明继承的父模板。父模板的路径,也是相对于 templates 文件夹下的绝对路径
{% extends "base.html" %}
block语法
一般在父模版中,定义一些公共的代码。子模板可能要根据具体的需求实现不同的代码。
这时候父模版就应该有能力提供一个接口,让子模板来实现。从而实现具体业务需求的功能。
父模板
{% block block的名字 %}
{% endblock %}
子模板
{% block block的名字 %}
子模板中的代码
{% endblock %}
调用父模版代码block中的代码
默认情况下,子模板如果实现了父模版定义的block。那么子模板 block中的代码就会覆盖掉父模板中的代码。
如果想要在子模板中仍然保持父模板中的代码,那么可以使用 {{ super() }} 来实现
父模板
{% block block_body %}
我是 父模版block_body处的内容
{% endblock %}
子模板
{% block block_body%}
{{ super() }}
我是子模版block_body处的内容
{% endblock %}
调用另外一个block中的代码
如果想要在另外一个模版中使用其他模版中的代码。那么可以通过 {{ self.其他block名字() }} 就可以了
{% block title %}
txc首页
{% endblock %}
{% block block_body%}
{{ self.title() }}
我是子模版block_body处的内容
{% endblock %}
注意
1. 子模板中的代码,第一行,应该是 extends
2. 子模板中,如果要实现自己的代码,应该放到block中。如果放到其他地方,那么就不会被渲染
实现如下页面,需要使用
1、模板继承
2、引入静态资源
简言之,python装饰器就是用于拓展原来函数功能的一种函数,这个函数的特殊之处在于它的返回值也是一个函数,
使用python装饰器的好处就是在不用更改原函数的代码前提下给函数增加新的功能。
1. 在视图函数中使用自定义装饰器,那么自己定义的装饰器必须放在 app.route 下面。
否则这个装饰器就起不到任何作用。
案例1
需求:查看设置个人信息时,只有检测到用户已经登录了才能查看,若没有登录,则无法查看并给出提示信息
定义装饰器
def login_required(func):
@wraps(func)
def wrapper(*arg,**kwargs):
uname = request.args.get('uname')
pwd = request.args.get('pwd')
if uname == 'zs' and pwd == '123':
logging.info(f'{uname}:登录成功')
return func(*arg,**kwargs)
else:
logging.info(f'{uname}:尝试登录,但没成功')
return '请先登录'
return wrapper
使用装饰器
@app.route('/settings/')
@login_requierd
def settings():
return '这是设置界面'
2. 在类视图中使用装饰器,需要重写类视图的一个类属性 decorators ,这个类属性是一个列表或者元组都可以,里面装的就是所有的装饰器。
案例2
需求: 查看设置个人信息时,只有检测到用户已经登录了才能查看,若没有登录,则无法查看并给出提示信息
使用装饰器
class ProfileView(views.View):
decorators = [login_requierd]
def dispatch_request(self):
return '这是个人中心界面'
app.add_url_rule('/profile/',view_func=ProfileView.as_view('profile'))
在Flask中,使用蓝图Blueprint来分模块组织管理。
蓝图实际可以理解为是存储一组视图方法的容器对象,其具有如下
特点:
1、一个应用可以具有多个Blueprint
2、可以将一个Blueprint注册到任何一个未使用的URL下比如 “/user” 、 “/goods”
3、Blueprint可以单独具有自己的模板、静态文件或者其它的通用操作方法,它并不是必须要实现应用的视图和函数的
4、在一个应用初始化时,就应该要注册需要使用的Blueprint
注意
Blueprint并不是一个完整的应用,它不能独立于应用运行,而必须要注册到某一个应用中
使用方式
使用蓝图可以分为三个步骤
1、创建一个蓝图对象
user_bp=Blueprint('user',__name__)
2、在这个蓝图对象上,
@user_bp.route('/')
def user_profile():
return 'user_profile'
3、在应用对象上注册这个蓝图对象
app.register_blueprint(user_bp)
可以将创建蓝图对象与定义视图放到一个文件中
import logging
from flask.blueprints import Blueprint
from flask import Flask
app = Flask(__name__)
logging.basicConfig(level=logging.INFO)
@app.route('/')
def index():
logging.info('输出了Hello!!')
return 'Hello'
user = Blueprint('user', __name__)
@user.route('/user')
def index():
return '用户模板'
app.register_blueprint(user)
if __name__ =='__main__':
app.run(debug=True)
指定蓝图的url前缀
在应用中注册蓝图时使用 url_prefix 参数指定
app.register_blueprint(user_bp,url_prefix='/user')
app.register_blueprint(goods_bp,url_prefix='/goods')
为了让项目代码更加清晰,可以通过将代码分在不同的文件里进行管理
根据功能模块
对于一个打算包含多个文件的蓝图,通常将创建蓝图对象放到Python包的 __init__.py 文件中
--------- project # 工程目录
|------ main.py # 启动文件
|------ user #用户蓝图
| |--- __init__.py # 此处创建蓝图对象
| |--- view.py
| |--- ...
|------ goods # 商品蓝图
| |--- __init__.py
| |--- ...
|...
根据技术模块
--------- project # 工程目录
|------ main.py # 启动文件
|------ view #用户蓝图
| |--- user.py # 此处创建蓝图对象
| |--- item.py
| |--- view.py
| |--- ...
|...
# main.py
from flask import Flask
import logging
app = Flask(__name__)
logging.basicConfig(level=logging.INFO)
@app.route('/')
def index():
logging.info('输出了Hello!!')
return 'Hello'
from user import user
app.register_blueprint(user)
if __name__ =='__main__':
app.run(debug=True)
# __init__.py
from flask.blueprints import Blueprint
user = Blueprint('user', __name__)
from user import view
# view.py
from user import user
@user.route('/user')
def index():
return '用户模板'
寻找规则
1、如果项目中的templates文件夹中有相应的模版文件,就直接使用了。
2、如果项目中的templates文件夹中没有相应的模版文件,那么就到在定义蓝图的时候指定的路径中寻找。2.1、并且蓝图中指定的路径可以为相对路径,相对的是当前这个蓝图文件所在的目录
因为这个蓝图文件是在user/view.py,那么就会到blueprints这个文件夹下的user_page文件夹中寻找模版文件。
小总结:
常规:蓝图文件在查找模版文件时,会以templates为根目录进行查找
user_bp = Blueprint('user',__name__,url_prefix='/user',template_folder='user_page')
注意
1、个性化coder喜欢在【创建蓝图对象的时候】 指定 模版文件的查找路径,如下
news_bp=Blueprint('news',__name__,url_prefix='/news',template_folder='news_page')
2、只有确定templates目录下没有对应的 html文件名的时候,才会去蓝图文件指定的目录下查找,指定才会生效
3、若templates目录下,有一个与蓝图文件指定的目录下同名的一个 html文件时,优先走templates目录下的东西
蓝图内部静态文件
蓝图对象创建时不会默认注册静态目录的路由。需要我们在创建时指定 static_folder 参数。
下面的示例将蓝图所在目录下的 static_admin 目录设置为静态目录
user=Blueprint("user",__name__,static_folder='user_static')
app.register_blueprint(admin,url_prefix='/user')
模板静态文件
也可通过 static_url_path 改变访问路径
user =Blueprint('user',__name__,template_folder='user_page',static_folder='user_static',static_url_path='/static')
app.register_blueprint(user,url_prefix='/user')
模板静态文件
如果使用蓝图,那么以后想要反转蓝图中的视图函数为url,就应该在使用url_for的时候指定这个蓝图名字。
app类中、模版中、同一个蓝图类中都是如此。否则就找不到这个endpoint
html文件中
新闻列表 OK写法
{# 新闻列表 no Ok写法#}
python文件中
from flask import
Blueprint,render_template,url_for
user_bp =Blueprint('news',__name__,url_prefix='/user',template_folder='user_page',static_folder= 'user_static')
@user_bp.route('/list/')
def user_list():
#如下写法:才找得到 url_for('蓝图名称.方法名')
print(url_for('user.user_list'))#/user/list/
print(url_for('user.user_detail'))#/user/detail/
return render_template('user_list.html')
@user_bp.route('/detail/')
def user_detail():
return '用户详情页面'
蓝图实现子域名:
1. 使用蓝图技术。
2. 在创建蓝图对象的时候,需要传递一个 subdomain 参数,来指定这个子域名的前缀。
cms_bp= Blueprint('cms',__name__,subdomain='cms')
3. 需要在主app文件中,需要配置app.config的SERVER_NAME参数。例如:
app.config['SERVER_NAME']='txc.com:5000'
4. 在windows: C:\Windows\System32\drivers\etc 下,找到hosts文件,然后添加域名与本机的映射。Linux: /etc/hosts
域名和子域名都需要做映射
127.0.0.1 txc.com
127.0.0.1 python.txc.com
注意
1、ip地址不能有子域名
2、localhost也不能有子域名