flask--app.add_url_rule()函数 和 类视图详解

flask--app.add_url_rule()函数 和 类视图详解

  1. app.add_url_rule()函数
    在flask中,我们知道给一个函数添加url的时候,只需要使用装饰器@app.route('')装饰对应的函数就可以了。为什么这个装饰器就可以给函数视图 添加url规则呢?查看app.route()源码发现,这个装饰器在里面调用的另外一个方法self.add_url_rule,这里的self就是app这个实例对象。

app.route()源码内容

def route(self, rule, **options):
	def decorator(f):
	    endpoint = options.pop("endpoint", None)
	    self.add_url_rule(rule, endpoint, f, **options)
	    return f
	
	return decorator

那么app.route这个装饰器就是通过调用add_url_rule这个方法生成函数视图对应的url的,那么我们可不可以我们自己直接调用这个方法来生成函数对应的url规则呢?答案是肯定的。

示例如下:

from flask import Flask

app = Flask(__name__)

def index():
	return 'index'

app.add_url_rule('/index/',endpoint='index',view_func=index)

add_url_rule三个参数解释:

  • 第一个参数:函数对应的url规则,满足条件和app.route()的第一个参数一样,必须以'/'开始
  • endpoint:站点,就是在使用url_for()进行反转的时候,这个里面传入的第一个参数就是这个endpoint对应的值。这个值也可以不指定,那么默认就会使用函数的名字作为endpoint的值
  • view_func:对应的函数,即这个url对应的是哪一个函数,注意,这里函数只需要写函数名字,不要加括号,加括号表示将函数的返回值传给了view_func参数了。程序就会直接报错。
# 正确的方式
app.add_url_rule('/index/',endpoint='index',view_func=index)
# 错误的方式
app.add_url_rule('/index/',endpoint='index',view_func=index())

  • methods:add_url_rule还可以传入一个methods参数,用来指定这个函数对应的访问规制,如post,get请求等,默认是get请求,并且只允许get请求。当我们需要改变请求方式的时候,我们就可以传入这个参数了。
# 指定一种
app.add_url_rule('/index/',endpoint='index',view_func=index,methods=['POST'])
# 指定多种
app.add_url_rule('/index/',endpoint='index',view_func=index,methods=['POST','get'])

注意:

  • 就算是只指定一种请求方式,也必须的用列表或元祖包裹起来,最好是用列表,元祖在某些情况下可能会出错。
  • 当元祖里面只有一个值得时候,后面必须的加一个,('post',)

2.什么是类视图

我们知道,在flask中,我们写的视图都是以函数形式写的,所以一般简称函数视图。其实视图我们也可以使用类来实现,类视图的好处是支持继承,但是类视图不能跟函数视图一样,写完类视图之后,我们还需要通过app.add_url_rule( url_rule, view_func )来进行注册。在flask中,有两种类视图。

3.标准类视图

标准类视图是继承自flask.views.View,并且在子类中必须实现dispatch_request方法,这个方法就是相当于视图函数,所有的逻辑操作我们都要放在这个里面完成。也必须的返回一个值,函数视图能返回什么类型的值,这里就可以返回什么类型的值。其实类视图和函数视图基本都是一样的,只是我们在做添加url规则的时候不一样而已。

from flask import Flask,views

app = Flask(__name__)

class ProfileView(views.View):

    def dispatch_request(self):
        return '个人中心页面'

app.add_url_rule('/profile/',endpoint='profile',view_func=ProfileView.as_view('profile'))

add_url_rule里面的参数的意思相信大家也知道了,这里说一下as_view里面传入的参数的意思吧。

  • View.as_view(’<指定函数的名称>’):因为我们所以的类视图都会继承自View类,并且都要重写dispatch_request方法,那么flask怎么知道我们绑定的是哪一个类的dispatch_request方法呢?就是通过这个参数来指定的。相当于给我们的dispatch_request方法起一个名字。当我们没有写endpoint参数的时候,那么endpoint的值就会是我们这个函数的名字。通过url_for进行反转的时候也是用的这个值。如果指定了endpoint的值,url_for就会使用endpoint的值,我们指定的函数名称对于我们来说没有什么太大的用处了,但是flask内部还是很有用处的。

4. 基于调度方法的视图

在flask中,还提供了另外一种类视图flask.views.MethodView,对每个HTTP的请求方法执行不同的函数,映射到对应小写的同名方法上面。例如:

class LoginView(views.MethodView):
    def get(self):
        return 'get 请求'

    def post(self):
        return 'post 请求'
        
app.add_url_rule('/login/',view_func=LoginView.as_view('login'))

这样,当我们以GET请求访问/login/页面的时候,就会执行get方法,以POST请求访问/login/页面的时候,就会执行post方法。

比如我们登陆的时候,如果用户使用的是get方法请求我们的页面,那么我们就渲染一个html页面给客户端,而当使用post方法请求的时候,我们就对上传的数据进行处理,然后返回相应的信息。

5.视图使用装饰器

假设我们现在有一个需求:如果用户请求的时候以get请求传入了username参数,我们就认为登陆了(模拟登陆的效果。),可以访问个人中心页面,否则的话就认为没有登陆。重定向到登陆页面。

这种需求我们一把都不会在视图中的逻辑代码中判断,而会定义一个装饰器。

定义装饰器:

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

app = Flask(__name__)

def login_require(fn):
    @wraps(fn)
    def wrapper(*args,**kwargs):
        username = request.args.get('username')
        if username and username == 'xxx':
            return fn(*args,**kwargs)
        else:
            return redirect( url_for('login') )
    return wrapper

    1. 函数视图使用装饰器。

上面我们就把装饰器定义好了,接下里我们就要开始使用这个装饰器了

@app.route('/login/')
def login():
	return 'login page'

@app.route('/profile/')
@login_require		# 使用我们写的login_require装饰器 这个装饰器必须放在@app.route()装饰器的下面
def profile():
	return '个人中心'

这样,我们就对我们的profile这个视图进行了装饰,如果输入网址为127.0.0.1:5000/profile/的时候,就会重定向到login视图中去。如果输入网址为127.0.0.1:5000/profile/?username=xxx才会被允许进入profile视图。当然,这里只是假设认为传入了username参数并且等于xxx就认为登陆了,在项目中肯定不会这样写的。在这里我们也只是为了知道装饰器的使用而已。

注意:

  • 如果我们使用app.route添加url规则的话,那么我们自己写的装饰器就必须放在app.route的下面。否则的话我们写的装饰器是没有作用的
  • 如果有多个装饰器的话。每个装饰器都必须放在app.route下面,然后就可以随便放置了。

3.类视图使用装饰器

使用views.View方法

class ProfileView(views.View):
	# 将这个视图所有的装饰器用decorators这个列表装起来
	decorators = [login_require]

	def dispatch_request(self):
		return '个人中心页面'

# 当然也可以直接装饰这个函数
class ProfileView(views.View):
	@login_require	
	def dispatch_request(self):
		return '个人中心页面'

app.add_url_rule('/profile/',view_func=Profile.as_view('profile'))

上面的两种方式都是可以的,至于用哪一种就看心情吧

  • 使用views.MethodView类

MethodView有三种方法进行装饰。

# 第一种,直接对相应的请求进行装饰
class ProfileView(views.MethodView):
	@login_require
	def get(self):
		return 'profile from get method'

	def post(self):
		return 'profile from post method'

# 第二种,重写dispatch_request方法,然后进行装饰
class ProfileView(views.MethodView):
	@login_require
	def dispatch_request(self,*args,**kwargs):
		return super().dispatch_request(*args,**kwargs)
		
	def get(self):
		return 'profile from get method'

	def post(self):
		return 'profile from post method'

# 第三中,使用decorators属性
class ProfileView(views.MethodView):
	decorators = [login_require]
		
	def get(self):
		return 'profile from get method'

	def post(self):
		return 'profile from post method'

app.add_url_rule('/profile/',view_func=Profile.as_view('profile'))

三种方式向使用哪一种都可以,看自己心情吧

posted @ 2023-05-05 17:22  布衣梦蝶1978  阅读(297)  评论(0编辑  收藏  举报