四时宝库

程序员的知识宝库

Flask的URL(flask的url_for)

发前简叙

  • 今年又负责年会的项目,公司700人的大会,我负责整个项目的前后,最近忙的喘不过气来,不过我还是坚持每天去更新这篇笔记,将每个案例代码都测试了一遍,想要给各位最好的学习Python经验,我也是小白,但是我从这个分享中,让我收获了很多的快乐。

处理请求

  • URL向视图函数传递参数
    • 传递参数的语法是/<参数名>/,同样这个“参数名”要与视图函数中的参数名保持一致。
    • 此外也可以使用“?key=value”的方式向视图函数传递。
    • 如果你的页面要做SEO优化(被搜索引擎搜索到),推荐使用第一种方式。
  • 路由匹配
    • 为了将不同的请求分发到对应的视图函数,程序的实例储存了一个路由表,这个路由表就定义了URL规则和视图函数的对应关系,如果没有找到对应的视图函数,则Flask自动返回404错误响应。
  • 转换器
    • 转换器规则:<转换器:变量名>。冒号为英文状态,中间不能有空格。Flask在解析URL请求时,会通过转换器将变量转换为对应的转换器数据类型。
    • 转换器分类:string,int,float,path,any,uuid。
    • 其中转换器any转换器的规则为:/<any(blog,article):url_path>/<id>/
    • 自定义转换器
      • 转换器其实是一个类,它继承自:from werkzeug.routing import BaseConverter。
      • 在自定义的转换器中。实现to_python(self, values)方法,这个方法返回的值,将会被传递到视图函数中作为参数。
      • 在自定义的转换器中。实现to_url(self, values)方法,这个方法的返回值,将会在调用url_for()函数时生成符合要求的URL形式。
from flask import Flask, url_for
from werkzeug.routing import BaseConverter

app = Flask(__name__)


# 在一个URL中有一个手机号码的变量,必须限制为手机号码的格式
class TelephoneConveter(BaseConverter):
 # 在自定义类中,需要重新写这个变量的正则表达式
 regex = r'1[3456789]\d{9}'


# 假设用户在访问/tags/a+b
class ListConveter(BaseConverter):
 def to_python(self, value):
 return value.split('+')

 def to_url(self, value):
 return '+'.join(value)


# 添加系统转换器的字典中
app.url_map.converters['tel'] = TelephoneConveter
app.url_map.converters['list'] = ListConveter


@app.route('/')
def hello_world():
 # 访问:http://127.0.0.1:5000/
 # 输出:/tags/a+b+c
 print(url_for('tags', boards=["a", 'b', 'c']))
 return "hello world"


@app.route('/telephone/<tel:my_tel>')
def my_tel(my_tel):
 return '您的手机号码是%s' % my_tel


@app.route('/tags/<list:boards>')
def tags(boards):
 # 访问:http://127.0.0.1:5000/tags/a+b+c
 # 输出:你提交的板块是['a', 'b', 'c']
 return "你提交的板块是%s" % boards


if __name__ == '__main__':
 app.run()
  • Request对象
    • 这个请求对象封装了从客户端发来的请求报文,我们能从这个请求报文中获取想要的数据。
    • request对象常用的方法和属性,这个可自行百度掌握,后续我这里也会逐步的说明,比如args,cookies,data,files、method等,具体的使用方法参照我如下的代码。
from flask import Flask, request
# import uuid
# print(uuid.uuid4())

app = Flask(__name__)


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


@app.route('/list/')
def show_list():
 return "文章列表"

# URL向视图函数传递“list_id”参数
# 必须保持URL和视图函数中的“list_id”保持一致
@app.route('/list/<list_id>')
def show_article(list_id):
 return "%s页文章" % list_id


# int转换器的使用方法
@app.route('/user/<int:user_id>')
def show_user(user_id):
 return '作者的id是%s' % user_id

# any转换器的使用方法
@app.route('/<any(blog, crm):url_path>/<demo>')
def show_root(url_path, demo):
 if url_path == "blog":
 return '博客id%s' % demo
 else:
 return 'crm的id%s' % demo

# 使用methods参数传入一个包含监听的HTTP方法的可迭代对象
# 使用methods参数传入一个包含监听的HTTP方法的可迭代对象
# Flask会自动返回一个405错误响应
@app.route('/root', methods=['GET', 'POST'])
def root():
 return "设置监听的参数"


# 通过问号的形式传递参数
# 利用request中的args属性获取参数的值
# 客户端的URL设置为http://127.0.0.1:5000/get/?name=alex
@app.route('/get/')
def get():
 arg = request.args.get('name')
 return '获取的name值为%s' % arg


if __name__ == '__main__':
 app.run()
  • url_for()函数
    • 如果将来修改了URL,但是没有修改与其对应的视图函数名称,使用url_for()函数就不用逐个修改URL了
    • url_for()会自动处理特殊的字符,不需要手动去处理。
    • 关于url_for()函数的参数解释,放在下面的代码块中了。
from flask import Flask, url_for
from werkzeug.routing import BaseConverter

app = Flask(__name__)

# 返回的是/list/1?count=2
# url_for第一个参数是视图函数的名字,数据类型为字符串
# 后面的参数是传递给视图函数,如果传递的参数在视图函数中已经定义
# 那么这个参数就会被当成path的形式给视图函数
# 如果这个参数之前没有在视图函数中定义
# 那么这个参数变成查询字符串的形式放到视图函数中
@app.route('/')
def hello_world():
 # 打印的是:/login?auth=%2F
 print(url_for('login', auth='/'))
 return url_for('my_list', page=1, count=2)


@app.route('/list/<page>')
def my_list(page):
 return "这是第%s页" % page


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


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

在局域网内访问你的网站

  • 局域网中其它电脑访问我的网站。需要在程序实例中设置host='0.0.0.0'的参数。
  • 指定端口号。Flask项目中,默认使用5000的端口,如果你想更换其它端口,那么需要设置port=9000的参数
  • URL唯一。在定义URL的时候,一定要在其后增加一个斜杠,否则有可能浏览器访问这个URL的时候,如果最后加了斜杠,那么就访问不到。
from flask import Flask, request

app = Flask(__name__)


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


@app.route('/blog')
def home():
 return "我的博客!"


# GET和POST请求区分
@app.route('/login/')
def login():
 if request.method == 'GET':
 return "GET请求"
 else:
 return 'POST请求'


if __name__ == '__main__':
 # 首先在其它的电脑中使用ping命令访问本电脑是否能够链接
 # 其次在其它的电脑浏览器中输入本机ip:9000即可访问
 app.run(host='0.0.0.0', port=9000)

页面跳转

  • 永久重定向。HTTP的状态码是301,多用于旧网址被废弃要转到一个新的网址确保用户的访问。
  • 暂时性重定向。HTTP的状态码是302,表示页面的暂时性跳转。例如访问有权限的网站,如果没有登录,应该重定向到登录页面。
from flask import Flask, request, redirect, url_for

app = Flask(__name__)


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


@app.route('/blog')
def home():
 if request.args.get('name'):
 return '欢迎登录'
 else:
 return redirect(url_for('login'), code=302)


@app.route('/login/')
def login():
 return '登录页面'


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

关于Response响应

  • 视图函数的返回值会被Flask自动转换一个响应对象,转换的逻辑如下。
    • 如果视图函数返回的是一个正常的Response对象,则直接返回。
    • 如果视图函数返回的是一个字符串,Flask会重新创建一个werkzeug.wrappers.Response对象,Response将该字符串作为主体返回,当然也包含报文协议、报文首部。
    • 如果视图函数返回的是一个元组,元组的格式为response,status,headers,status是状态码,headers可以是列表、字典作为头信息。
    • 如果视图函数返回的内容都不满足,Flask会假设返回值是一个合法的WSGI的应用程序,通过Response.force_type(rv, request.environ)转换为一个请求的对象。
from flask import Flask, jsonify
from werkzeug.wrappers import Response
# flask=werkgeug+sqlalchemy+jinja2

app = Flask(__name__)


# 必须继承自Response类
# 必须实现类方法force_type()
# 必须指定app.
class JsonResponse(Response):
 # 这个方法只有是视图函数返回非响应的字段才会使用,例如列表
 @classmethod
 def force_type(cls, response, environ=None):
 if isinstance(response, dict):
 # jsonify()将字典转换成json对象,还生成一个response对象
 response = jsonify(response)
 return super(JsonResponse, cls).force_type(response, environ)


app.response_class = JsonResponse


@app.route('/')
def hello_world():
 # 等同于Response('hello', status=200, content_type='text/html')
 return 'Hello World!'


@app.route('/blog')
def blog():
 # 如果直接['a', 'b'],在浏览器访问该URL时会报错。
 return 'blog', 200, {'name': 'chain'}


@app.route('/articles')
def my_articles():
 return {'title': "new world", 'tag': 'python'}


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

发表评论:

控制面板
您好,欢迎到访网站!
  查看权限
网站分类
最新留言
    友情链接