资讯专栏INFORMATION COLUMN

flask之三:视图高级

xumenger / 372人阅读

摘要:视图高级和这个方法是用来添加与视图函数的映射。小例子如下请求上下文的定义,结合类视图之前我们接触的视图都是函数,所以一般简称视图函数。

视图高级 app.routeapp.add_url_rule

app.add_url_rule

app.add_url_rule("/list/",endpoint="myweb",view_func=my_list)

这个方法是用来添加url视图函数的映射。如果没有填写endpoint那么会默认使用view_func的名字来作为endpoint
因此在使用url_for的时候,就要看在映射的时候有没有传递endpoint参数,如果传递了,那么就使用endpoint指定的字符串。
付过没有使用的话就使用view_func定义的名字。

app.route(rule,**options)装饰器

这个装饰器的底层就是用add_url_rule来实现url与视图函数映射的。

小例子如下:

from flask import Flask,url_for
app = Flask(__name__)
app.config.update({
    "DEBUG":True,
    "TEMPLATES_AUTO_RELOAD":True
})
@app.route("/",endpoint="index")
def hello_world():
    print(url_for("myweb"))
    return "Hello World!"
def my_list():
    return "list page!"
app.add_url_rule("/list/",endpoint="myweb",view_func=my_list)
#请求上下文的定义,结合url_for
with app.test_request_context():
    print(url_for("index"))
if __name__ == "__main__":
    app.run()
类视图

之前我们接触的视图都是函数,所以一般简称视图函数。
其实视图也可以基于类来实现,类视图的好处是支持继承,但是类视图不能跟函数视图一样,
写完类视图还需要通过app.add_url_rule(url_rule,view_func)来进行注册。以下将对两种类视图进行讲解

标准视图

标准类视图必须继承自flask.views.View

必须实现dispatch_request方法,以后请求过来以后,会执行这个方法。这个方法的返回值就相当于是之前的函数视图一样,也必须返回Request或者子类的对象(字符串或者元组)。

必须是通过app.add_url_rule(rule,endpoint,view_func)来做url映射。

view_func这个参数,要使用as_view这个方法来转换

如果指定了endpoint,那么在使用url_for反转的时候,就要使用endpoint指定的那个值,如果没有指定那个值,就使用as_view中指定的视图名字来作为反转。

类视图有以下的好处,可以将一些共性的东西抽取出来放到父视图中,子视图直接继承就可以了,但是也不是说所有的视图都要使用类视图,这个要根据实际情况来定。

小例子:

from flask import Flask,views,url_for
app = Flask(__name__)
class ListView(views.View):
    def dispatch_request(self):
        return "list view"
#app.add_url_rule("/list/",endpoint="list",view_func=ListView.as_view("list"))
app.add_url_rule("/list/",view_func=ListView.as_view("list"))
with app.test_request_context():
    print(url_for("list"))
@app.route("/")
def hello_world():
    return "Hello World!"
if __name__ == "__main__":
    app.run(debug=True)

类视图的小例子:

from flask import Flask,url_for,views,jsonify,render_template

app = Flask(__name__)
app.config.update({
    "DEBUG":True,
    "TEMPLATES_AUTO_RELOAD":True
})

#自定义封装,返回json数据
class JSONView(views.View):
    def get_data(self):
        raise NotImplementedError
    def dispatch_request(self):
        return jsonify(self.get_data())

class ListView(JSONView):
    def get_data(self):
        return {
            "username":"wanghui",
            "password":123456,
        }

app.add_url_rule("/list/",endpoint="my_list",view_func=ListView.as_view("list"))
#有几个视图,需要返回相同的变量(广告页面)
class ADSView(views.View):
    def __init__(self):
        super(ADSView, self).__init__()
        self.context = {
            "ads":"今年过节不收礼,收礼只收脑白金"
        }
class RegistView(ADSView):
    def dispatch_request(self):
        self.context.update({"username":"abcd"})
        return render_template("register.html",**self.context)
class LoginView(ADSView):
    def dispatch_request(self):
        return render_template("login.html",**self.context)
# class LoginView(views.View):
#     def dispatch_request(self):
#         return render_template("login.html",ads="今年过节不收礼,收礼只收脑白金")
# class RegistView(views.View):
#     def dispatch_request(self):
#         return render_template("register.html",ads="今年过节不收礼,收礼只收脑白金")
app.add_url_rule("/login/",view_func=LoginView.as_view("login"))
app.add_url_rule("/regist/",view_func=RegistView.as_view("regist"))

@app.route("/")
def hello():
    return "heello"
if __name__ == "__main__":
    app.run()
基于调度方法的视图

根据请求方法来执行不同的方法的,如果用户发送的是get请求,就会执行这个类的get方法;如果用户发起的是post方法,就会执行这个类的post方法。其他的方法类似,这种方法使得代码更加简洁,使得执行get请求的代码放在get方法中,post请求的代码放在posy方法中。就不需要跟之前的request.method == "POST"来搞了。

小例子

py

from flask import Flask,views,render_template,request

app = Flask(__name__)

class LoginView(views.MethodView):
    def __render(self,error=None):
        return render_template("login.html",error=error)
    def get(self,error=None):
        # return render_template("login.html",error=error)
        return self.__render()
    def post(self):
        username = request.form.get("username")
        password = request.form.get("password")
        if username == "wanghui" and password == "111111":
            return "login success"
        else:
            # return render_template("login.html",error="username or password error,retry!")
            # return self.get(error="username or password error,retry!")
            return self.__render(error="username or password error,retry!")

app.add_url_rule("/login/",view_func=LoginView.as_view("login"))

@app.route("/")
def hello_world():
    return "Hello World!"

if __name__ == "__main__":
    app.run(debug=True,port=9090)

login.html




    
    login


用户名
密码
{% if error %}

{{ error }}

{% endif %}
类视图上面使用装饰器

两种类型的装饰器

如果使用的是函数视图, 那么定义的装饰器必须放在app.route下面,否则起不到任何作用

类视图的装饰器,需要重写类视图的decorators类属性,里面装的就是所有的装饰器

小例子:

from flask import Flask,request,views
from functools import wraps

app = Flask(__name__)

#定义装饰器
def login_required(func):
    @wraps(func)
    def wrapper(*args,**kwargs):
        username = request.args.get("username")
        if username and username == "wanghui":
            return func(*args,**kwargs)
        else:
            return "请先登录"
    return wrapper


@app.route("/settings/")
@login_required
def settings():
    return "这是设置页面"

#这样请求就行http://127.0.0.1:9091/settings/?username=wanghui

#类视图添加装饰器
class ProfileView(views.View):
    decorators = [login_required]
    def dispatch_request(self):
        return "这是个人中心"
app.add_url_rule("/profile/",view_func=ProfileView.as_view("profile"))
蓝图
将大型项目分层解耦,实现模块化,结构更加清晰。可以将相同的模块放在同一个蓝图下,同一个文件夹中。方便管理。

基本语法:

在蓝图文件中导入Blueprint

from flask import Blueprint
user_bp = Blueprint("user",__name__)    #相当于是定义`app = Flask(__name__)`

在主app文件中注册蓝图

from blueprints.user import user_bp
app.regist_blueprint(user_bp)   #实现注册蓝图

如果想要某个蓝图下的所有URL的时候有个前缀,那么可以在定义蓝图的时候加上url_prefix

from flask import Blueprint
user_bp = Blueprint("user",__name__,url_prefix="/user") 
# 特别注意斜杠
蓝图中的模板文件

蓝图模板文件查找:

如果项目中的templates文件夹中存在对应的模板文件,就可以直接使用

如果项目中的templates文件夹中存在相应的模板文件,那么就在定义蓝图的指定路径中查找,可以设置相对路径,就要在蓝图文件相同路径下的文件夹。

from flask import Blueprint,render_template
news_bp = Blueprint("news",__name__,url_prefix="/news",template_folder="news")
@news_bp.route("/list/")
def news_list():
    return render_template("news_list.html")

蓝图中的静态文件查找:

在模板文件中,加载静态文件,如果使用url_for("static"),那么只会在app指定的静态文件夹目录下查找静态文件

如果在加载静态文件的时候置顶了蓝图的名字,比如url_for("news.static"),那么会到蓝图指定的static_folder下查找静态文件。

url_for反转蓝图注意事项

注意url_for到蓝图中的视图函数的时候,要反转蓝图中的视图函数为url,那么就用该在使用url_for的时候使用url_for("news.news_list")不然就找不到这个endpoint。

即使在同一个蓝图中,反转视图函数,也要制定蓝图的名字

子域名实现

使用蓝图技术

在创建蓝图对象的时候要使用subdomain来指定这个子域名

from flask import Blueprint
cms_bp = Blueprint("cms",__name__,subdomain="cms")

需要在app文件中配置app.config["SERVER_NAME"]="baidu.com"来指定跟域名

app.config["SERVER_NAME"] = "crop.com:9099"

修改hosts文件配置解析

127.0.0.1 crop.com
127.0.0.1 cms.crop.com

5.访问

cms.crop.com:9099
综合实例代码

目录结构

blue_print_e
├── blue_print_e.py
├── blueprints
│ ├── bok.py
│ ├── cms.py
│ ├── movie.py
│ ├── news_css
│ │ └── news_list.css
│ ├── news.py
│ ├── news_tmp
│ │ └── news_list.html
│ └── user.py
├── static
│ └── news_list.css
└── templates
    ├── index.html
    └── news_list.html

主app文件blue_print_e.py

from flask import Flask,url_for,render_template
from blueprints.user import user_bp
from blueprints.news import news_bp
from blueprints.cms import cms_bp

app = Flask(__name__)
app.config["SERVER_NAME"] = "crop.com:9099"

app.register_blueprint(user_bp)
app.register_blueprint(news_bp)
app.register_blueprint(cms_bp)
# ip地址不能有子域名
@app.route("/")
def hello_world():
    print(url_for("news_tmp.news_list"))     #使用蓝图名字.视图函数的名字
    return render_template("index.html")
if __name__ == "__main__":
    app.run(debug=True,port=9099)

blueprints/news.py

#!/usr/bin/env python
# -*- coding: utf-8 -*-
from flask import Blueprint,render_template,url_for

news_bp = Blueprint("news_tmp",__name__,url_prefix="/news_tmp",template_folder="news_tmp",static_folder="news_css")

@news_bp.route("/list/")
def news_list():
    print(url_for("news.news_detail"))
    return render_template("news_list.html")

@news_bp.route("/detail")
def news_detail():
    return "详情页面"

blueprints/user.py

#!/usr/bin/env python
# -*- coding: utf-8 -*-
from flask import Blueprint

user_bp = Blueprint("user",__name__,url_prefix="/user")
@user_bp.route("/profile/")
def profile():
    return "个人中心"

@user_bp.route("/settings/")
def settings():
    return "设置页面"

blueprint/cms.py

#!/usr/bin/env python
# -*- coding: utf-8 -*-
from flask import Blueprint
cms_bp = Blueprint("cms",__name__,subdomain="cms")
@cms_bp.route("/")
def index():
    return "cms index"

blueprints/news_css/

body {
    color: fuchsia;
    font-size: 90px;
    background: red;
}

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/52281.html

相关文章

  • flask之三视图高级

    摘要:视图高级和这个方法是用来添加与视图函数的映射。小例子如下请求上下文的定义,结合类视图之前我们接触的视图都是函数,所以一般简称视图函数。 视图高级 app.route和app.add_url_rule app.add_url_rule app.add_url_rule(/list/,endpoint=myweb,view_func=my_list) 这个方法是用来添加url与视图函数...

    hot_pot_Leo 评论0 收藏0
  • flask之三视图高级

    摘要:视图高级和这个方法是用来添加与视图函数的映射。小例子如下请求上下文的定义,结合类视图之前我们接触的视图都是函数,所以一般简称视图函数。 视图高级 app.route和app.add_url_rule app.add_url_rule app.add_url_rule(/list/,endpoint=myweb,view_func=my_list) 这个方法是用来添加url与视图函数...

    RancherLabs 评论0 收藏0
  • Django基础之三(类视图

    摘要:类视图简介视图是一个可调用的对象,它接收一个请求然后返回一个响应,这个可调用对象可以不只是函数,提供一些可以用作视图的类基于类的视图使用对象实现视图,它提供除函数视图之外的另外一种方式属性添加未知的请求方法方法将类视图转换成可被调用的函数视 类视图 简介 视图是一个可调用的对象,它接收一个请求然后返回一个响应,这个可调用对象可以不只是函数,Django提供一些可以用作视图的类基于类的视...

    PAMPANG 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<