Flask之视图高级(二)

发布于:2022-11-09 ⋅ 阅读:(518) ⋅ 点赞:(0)

目录

类视图&装饰器

基于调度方法的类视图

基于调度方法的类视图写法优化 

视图装饰器的使用

蓝图

蓝图的介绍

使用方法

蓝图的url前缀:

蓝图的目录结构

蓝图模板的使用

templates的寻找规则

蓝图静态文件

蓝图内部静态文件

蓝图与url_for函数的结合

蓝图设置子域名

蓝图实现子域名


类视图&装饰器

基于调度方法的类视图

1.基于调度方法的类视图,可以根据不同的method来执行不同的请求。假如用户发送的get请求,则会自动执行这个类get方法。

2.将get请求相关的代码放在get方法中,与post请求相关的代码都放在post方法中,就不需要通过之前的request.method  == ‘GET’  了。可以让代码更加的简洁,方便。

这是未使用调度方法类视图的原代码:

可以看到,现在完美使用的方法需要写method=【‘post’,‘get’】以及逐个判断是否为post或者get请求。

from flask import Flask,render_template,request

app = Flask(__name__)

@app.route('/login/',methods=['GET','POST'])
def login():
    if request.method == 'GET':
        return render_template('login05.html')
    elif request.method == 'POST':
        uname = request.form.get('uname')
        pwd = request.form.get('pwd')
        if uname == 'xiaolin' and pwd == '123456':
            return '登录成功!'
        else:
            return render_template('login05.html')

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

改进后:

不需要对请求类型进行判断。

from flask import Flask,render_template,request
from flask.views import MethodView

app = Flask(__name__)

class loginView(MethodView):
    def get(self):
        return render_template('login05.html')
    def post(self):        
        uname = request.form.get('uname')
        pwd = request.form.get('pwd')
        if uname == 'xiaolin' and pwd == '123456':
            return '登录成功!'
        else:
            return render_template('login05.html',msg='用户名或者密码错误!')

app.add_url_rule('/login/',view_func=loginView.as_view('login'))



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

基于调度方法的类视图写法优化 

优化写法:

from flask import Flask,render_template,request
from flask.views import MethodView

app = Flask(__name__)

class logView(MethodView):
    def _jump(self,msg = None):
        return render_template('login06.html',msg = msg)
    def get(self,msg = None):
        return self._jump()
    def post(self):
        uname = request.form.get('uname')
        pwd = request.form.get('pwd')
        if uname == 'xiaolin' and pwd == '123456':
            return '欢迎小林'
        else:
            return self._jump(msg = '用户名或者密码错误!请输入正确的的用户名和密码!')


app.add_url_rule('/login/',view_func=logView.as_view('login'))

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

 

 其实主要是 render_template()这里出现了重复,可以创建一个函数单独写出去,在进行调用即可。在多次要使用重复代码的时候,可以使用,以减少代码量。

视图装饰器的使用

python装饰器:用于扩展原来函数的功能的函数,特殊之处在于它的返回值是一个函数。

优点:在不用更改原函数的代码的前提下,给函数增加新的功能。

注意:在视图函数中使用自定义装饰器,必须放在app.route()下,否则这个装饰器将不起任何作用。

例:

一个验证用户是否登录成功的装饰器 ,会将登录成功或者失败的信息传递给后台。

from flask import Flask,render_template,request
from functools import wraps
import logging

app = Flask(__name__)

# 设置日志模块
logging.basicConfig(level=logging.INFO)

def login_required(func):
    @wraps(func)
    def wrapper(*args,**kwargs):
        uname = request.args.get('uname')
        pwd = request.args.get('pwd')
        if uname == 'xiaolin' and pwd == '123456':
            logging.info(f'{uname}:登录成功!!')
            return func(*args,**kwargs)
        else:
            logging.info(f'{uname}:尝试登录失败!!')
            return '用户名或密码错误!'
    return wrapper

@app.route('/')
@login_required
def index():
    return 'hello'

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

在类视图中使用装饰器,需要重写类视图的一个类属性decorators,这个类属性是一个列表或者元组都可以,里面装的就是所有的装饰器。

@app.route('/')
@login_required
def index():
    return 'hello'

class LoginViwe(MethodView):
    decorators=[login_required]
    def get(self):
        return 'hello'

app.add_url_rule('/login/',view_func=LoginViwe.as_view('login'))

蓝图

蓝图里老是映射来映射去,烦死了有时候都搞不清楚了。

蓝图的介绍

蓝图我个人理解的话就是一个容器。

在Flask中,使用蓝图Blueprint来分模块组织管理。

那么它具有以下的特点:

  • 一个应用可以具有多个Blueprint
  • 可以将一个Blueprint注册到任何一个未使用的URL下比如“/user”“/goods”
  • Blueprint可以单独具有自己的模板、静态文件或者其它的通用操作方法,它并不是必须要实现应用的视图和函数的
  • 在一个应用初始化时,就应该要注册需要使用的Blueprint

注意

Blueprint并不是一个完整的应用,它不能独立于应用运行,而必须要注册到某一个应用中

以一个简单的购物页面来看:

        

#用户模块

    #登录模块

    #注册模块

    #退出模块

#产品模块  

    #获取全部产品

    #获取单件产品

    #更新产品

    #删除产品

    #批量添加产品

#收藏模块

#购物车模块

可以看到就单单几个模块就以及足够复杂了,所需要的代码量是很大的了。当产品模块需要更改的时候,时间也是很费劲的。而且若是书写不规范的模块或者耦合性高的模块间,需要修改更加费时费力。

这时候蓝图就很重要了,每一个模块都能单独创建一个蓝图来批量管理里面的子模块,不需要的时候可以直接删除该文件夹。

使用方法

1.创建一个蓝图对象(这里是用户模块):

user_pb = breakpoint('user',__name__)

2.给蓝图创建一个需要管理的蓝图地址:

@user_pb.route('/login/')
def login():
    return '登录模块'

@user_pb.route('/register/')
def register():
    return '注册模块'

3.需要注册这个蓝图对象:

app.register_blueprint(user_pb)

蓝图的url前缀:

可以为蓝图添加一个独特的前缀,增加辨识度。

app.register_blueprint(user_bp, url_prefix='/user')

蓝图的目录结构

在接着上一个蓝图的使用后,现在完美仍然将蓝图放在一个文件里边,造成的结果就是仍然显得很臃肿和复杂。那么为了让每个模块更加清晰,可以通过将代码分在不同的文件里进行集中管理。

可以根据功能模块和技术模块分别创建工程目录,不多赘述。

蓝图模板的使用

templates的寻找规则

  • 如果项目中的templates文件夹中有相应的模版文件,就直接使用了。

  • 如果项目中的templates文件夹中没有相应的模版文件,那么就到在定义蓝图的时候指定的路径中寻找。

    • 并且蓝图中指定的路径可以为相对路径,相对的是当前这个蓝图文件所在的目录

在正常情况下,蓝图文件在寻找模块文件时,会以templates为根目录来进行查询。

user_bp = Blueprint('user',__name__,url_prefix='/user',template_folder='user_page')

蓝图静态文件

模板中可以有独有的静态文件

蓝图内部静态文件

蓝图对象创建时不会默认注册静态目录的路由。需要我们在创建时指定 static_folder 参数。

例:

将蓝图目录下的static_admin目录设置为静态目录

user=Blueprint("user",__name__,static_folder='user_static')
app.register_blueprint(admin,url_prefix='/user')
<body>
  <h1>模板静态文件</h1>
  <video src="/user/user_static/aaa.mp4" autoplay width="50%" loop="loop" muted='muted'></video>
</body>

 可以通过static_url_path改变访问,这个就不做实例了。

蓝图与url_for函数的结合

跟以往不同,在蓝图中使用url_for跟默认写法不同,需要在url_for后边指定蓝图的名字。

app类中、模版中、同一个蓝图类中都是如此。否则就找不到这个endpoint

在python中:

from user import user_bp
from flask import url_for

@user_bp.route('/index/')
def index():
    return '用户主页'

@user_bp.route('/')
def test_url():
    return url_for('user.index')

在html中:

    <video src='{{url_for("user.static",filename="aaa.mp4")}}' autoplay muted="meted" loop="loop"></video>

蓝图设置子域名

很多应用都带有子应用,比如百度里的百度地图,百度贴吧,百度新闻等等。子应用的域名基本上相等,但是前缀不同,可以利用蓝图来实现子域名。

蓝图实现子域名

1.使用蓝图技术。

2.创建蓝图对象的时候,添加一个传递一个subdomain参数,来指定子域名的前缀:

cms_bp= Blueprint('cms',__name__,subdomain='cms')

3. 需要在主app文件中,需要配置app.config的SERVER_NAME参数。

if __name__ == '__main__':
    # 127.0.0.1:5000
    app.config['SERVER_NAME'] = 'xiaolin.com:5000'
    app.run(debug=True)

  4.在windows:C:\Windows\System32\drivers\etc下,找到hosts文件,然后添加域名与本机的映射。Linux: /etc/hosts。

域名和子域名都需要做映射。

 这个很烦啊!!!!!!!

这样改(例):

127.0.0.1 xiaolin.com

127.0.0.1 python.xiaolin.com

注意

  • ip地址不能有子域名
  • localhost也不能有子域名

————————————————————————————————————————

Flask之视图高级---->END

本文含有隐藏内容,请 开通VIP 后查看