• flask之URL和视图(一)-----url传参的方法


    1.1.第一个flask程序

    复制代码
    from flask import Flask
    #创建一个Flask对象,传递__name__参数进去
    app = Flask(__name__)
    
    #url与视图映射
    @app.route('/')
    def hello_world():
        return 'Hello World!'
    
    
    if __name__ == '__main__':
        app.run()   #flask中的一个测试应用服务器
    复制代码

    浏览器访问:http://127.0.0.1:5000/,也可以更改端口号: app.run(port=5001)

    1.2.debug模式

     作用:

    • 如果抛出异常,在浏览器中可以看到具体错误信息
    • 在修改代码后,只要按“ctrl+s”,就会自动重启项目,不用手动重新运行

    四种配置方式

    第一种

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

    第二种

    app.debug = True

    第三种

    app.config.update(DEBUG=True)

    第四种

    新建config.py

    DEBUG = Ture

    然后在主程序总导入引用

    cnfig文件
    import config app.config.from_object(config)


    另外的执行文件
    from flask import Flask
    import config
    #创建一个Flask对象,传递__name__参数进去
    app = Flask(__name__)
    # app.debug = True   #第二种
    # app.config.update(DEBUG=True)  #第三种
    app.config.from_object(config)   #第四种
    
    #url与视图映射
    @app.route('/')
    def hello_world():
        print('helloworkl')
        return 'Hello World!'
    
    if __name__ == '__main__':
        # app.run(debug=True)   #第一种
        app.run()

    1.3.配置文件

    新建config.py

    DEBUG =True

    主程序中两种引用方式

    第一种:

    import config
    
    app.config.from_object(config)  

    第二种

    app.config.from_pyfile('config.py')

    1.4.url传参方式

    普通传参方式

    @app.route('/p/<id>/')
    def article_detail(id):
        return '你访问的文章第%s篇'%id

    指定参数类型

    有以下几种类型:

    • string:默认的数据类型
    • int:接受整形
    • float:浮点型
    • path:和string的类似,但是接受斜杠
    • any:可以指定多个路径
    • uuid:只接受uuid字符串

     (1)any

    @app.route('/<any(blog,user):url_path>/<id>')
    def detail(url_path,id):
        if url_path == 'blog':
            return '博客详情%s'%id
        else:
            return '用户详情%s'%id

     

     (2)path

    @app.route('/article/<path:test>/')
    def test_article(test):
        return 'test_article:{}'.format(test)

    获取参数

    from flask import Flask,request
    
    @app.route('/tieba/')
    def tieba():
        wd = request.args.get('wd')
        return '获取的参数的是%s'%wd

    1.5.url_for的使用

    (1)通过视图函数解析出url

    复制代码
    from flask import Flask,url_for
    
    @app.route('/')
    def hello_world():
        return url_for('my_list',page=2)   #url_for里面:第一个是视图函数,第二个是url需要的参数
    
    @app.route('/list/<page>/')
    def my_list(page):
        return 'my_list'
    复制代码

    (2)url_for里面多的参数会当做搜索字符

    复制代码
    @app.route('/')
    def hello_world():
        return url_for('my_list',page=2,count=2)   
    
    @app.route('/list/<page>/')
    def my_list(page):
        return 'my_list'
    复制代码

    1.6.Response

     视图函数中可以返回的类型

    • 可以返回字符串,返回的字符串其实底层将这个字符串包装成了一个‘Response’对象
    • 可以返回元组,形式(响应体,状态码,头部信息),返回的元组其实底层将这个字符串包装成了一个‘Response’对象
    • 可以返回Response及其子类

    实现一个自定义的Response对象

    • 继承自、‘Response’类
    • 实现方法‘force_type’
    • 指定‘app.response_class’为你自定义的‘Response’对象
    • 如果视图函数返回的数据,不是字符串,也不是元组,也不是Response对象,那么就会将返回值传给‘force_type’,然后将‘force_type’的返回值返回给前端 

    实例:

    复制代码
    from flask import Flask,url_for,Response,jsonify
    
    app = Flask(__name__)
    
    class JsonResponse(Response):
    
        @classmethod
        def force_type(cls, response, environ=None):
            '''
            这个方法只有视图函数返回非字符、非元祖、非Response对象才会调用
            :param response:
            :param environ:
            :return:
            '''
            #把字典转换成json
            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():
        return 'Hello world'
    
    @app.route('/list1/')
    def list1():
        return Response('list1')  #合法对象,直接返回
    
    @app.route('/list3/')
    def list3():
        return {'username':'derek','age':18}   #返回的是非字符、非元祖、非Response对象,所以执行force_type方法
    
    if __name__ == '__main__':
    
        app.run(debug=True)
    复制代码
    因为/list3/返回的是字典类型,非字符、非元祖、非Response对象,所以执行force_type方法

    1.7.add_url_rule

    源码

    主程序

    复制代码
    from flask import Flask,render_template,url_for
    
    app = Flask(__name__)
    app.config.update({
        'DEBUG':True,
        'TEMPLATES_AUTO_RELOAD':True
    })
    
    @app.route('/',endpoint='index')   
    def hello_world():
        print(url_for("derek_list"))    #通过endpoint找到对应的url   /list/
        return render_template('index.html')
    
    def my_list():
        return "列表页"
    
    #三个参数
    #1.url
    #2.给url起个别名,如果没有指定endpoint,则默认使用视图函数的名字作为endpoint的值
    #3.视图函数
    app.add_url_rule('/list/',endpoint='derek_list',view_func=my_list)
    
    with app.test_request_context():
        print(url_for('index'))    # /
    
    if __name__ == '__main__':
        app.run()
    复制代码

    1.8.类视图

    之前使用的视图都是函数,简称为视图函数,视图也可以基于类来实现,类视图的好处是支持继承,类视图需要通过app.add_url_role(url_rule,view_func)来进行注册,类里面要加装饰器就用:detactors=[]   ,里面可以添加多个装饰器

     (1)标准视图

    • 继承views.VIew
    • 必须实现‘dispatch_request’方法,以后请求过来后,都会执行这个方法,返回值相当于视图函数一样,必须返回'Response'或者子类的对象,或者是字符串,或者是元祖
    • 必须通过app.add_url_role(url_rule,view_func)来做url与视图的映射

    实例

    复制代码
    from flask import Flask,url_for,views
    
    app = Flask(__name__)
    app.config.update({
        'DEBUG':True,
        'TEMPLATES_AUTO_RELOAD':True
    })
    
    class ListView(views.View):
        def dispatch_request(self):
            return "我的列表页"
    
    # 1.ListView.as_view('list')里面必须传个参数‘name’,给view_func起个别名,实际上就是dispatch_request函数
    # 2.endpoint也可以不指定,则默认使用view_func的别名(name参数的值)
    app.add_url_rule('/list/',endpoint='list',view_func=ListView.as_view('list'))
    
    
    @app.route('/')
    def hello_world():
        return 'Hello World!'
    
    with app.test_request_context():
        print(url_for('list'))    #/list/
    
    if __name__ == '__main__':
        app.run()
    复制代码

    (2)通过类的继承实现多个视图返回json数据

    复制代码
    from flask import Flask,url_for,views,jsonify
    
    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())
    
    #子类只需要写get_data方法
    class ListView(JsonView):
        def get_data(self):
            return {"usernmae":'derek','age':18}
    
    app.add_url_rule('/list/',endpoint='list',view_func=ListView.as_view('list'))
    
    
    @app.route('/')
    def hello_world():
        return 'Hello World!'
    
    if __name__ == '__main__':
        app.run()
    复制代码

      (3)基于调度方法的类视图 

    复制代码
    class LoginView(views.MethodView):
        def __render(self,error=None):
            return render_template('login.html', error=error)
    
        def get(self,error=None):
            return self.__render()
    
        def post(self):
            username = request.form.get('username')
            password = request.form.get('password')
            if username == 'derek' and password == '123':
                return '登录成功'
            else:
                return self.__render(error='用户名或密码错误')
    
    app.add_url_rule('/login/',view_func=LoginView.as_view('login'))
    复制代码
     

    来源: https://www.cnblogs.com/sui776265233/p/9879533.html#_label0

    后记:

    这个传惨的方法可能会报错  UnicodeDecodeError: 'ascii' codec can't decode byte 0xe9 in position 0: ordinal not in range(128)

    原因: 因为默认情况下,Python采用的是ascii编码方式,而Python在进行编码方式之间的转换时,会将 unicode 作为“中间编码”,但 unicode 最大只有 128 那么长,所以这里当尝试将 ascii 编码字符串转换成"中间编码" unicode 时由于超出了其范围,就报出了如上错误。

    解决方法: 在文件上方加上

    import sys
    reload(sys)
    sys.setdefaultencoding('utf-8')

    例子:

    #coding=utf-8
    from flask import Flask
    import sys
    reload(sys)
    sys.setdefaultencoding('utf-8')

    app = Flask(__name__)
    app.config.from_object('config')

    @app.route("/hello/<id>/")
    def hello(id):
      return '你访问的文章第%s篇'%id

    app.run(host="0.0.0.0",debug=app.config["DEBUG"])

    后记: 有更加优雅和简单的方法实现 https://www.cnblogs.com/kaibindirver/p/12637027.html

  • 相关阅读:
    深入Activity
    swift -变量的定义与使用
    tomcat中的Manager App帐号password管理
    TabLayout+Fragment+ViewPager+FragmentStatePagerAdapter实现Tab标签
    基于redis的分布式ID生成器
    Event-Souring模式
    Tensorflow
    RabbitMQ消息队列(五):Routing 消息路由
    RabbitMQ消息队列(四):分发到多Consumer(Publish/Subscribe)
    RabbitMQ消息队列(三):任务分发机制
  • 原文地址:https://www.cnblogs.com/kaibindirver/p/12555517.html
Copyright © 2020-2023  润新知