首页 > 其他分享 >flask(二)

flask(二)

时间:2022-12-11 21:44:26浏览次数:46  
标签:endpoint return name flask app rule view

今日内容概要

  • flask展示用户信息案例

  • 配置文件写法

  • 路由系统

  • 路由本质

  • cbv写法

  • 模板语法

今日内容详细

flask展示用户信息案例

需求:

  1. 登录:返回给前端cookie
  2. 登录成功后可以访问首页(不登录不能访问)
  3. 点击首页的详情,访问详情(不登录不能访问)
from flask import Flask,request,render_template,redirect,session

app = Flask(__name__)

app.secret_key='zjj123456789zmpasdasd'
USERS={
    1:{"name":"掌上","text":'1235461'},
    2:{"name":"掌上11","text":'1235461111'},
    3:{"name":"掌上111","text":'123546111111'},   
}

def outer(func_name):  # func_name用于接收被装饰的对象(函数)
    def inner(*args, **kwargs):
        if session.get('username') == 'zjj':
            res = func_name(*args, **kwargs)
            return res
        else:
            return redirect('/login')
    return inner
@app.route('/')
def hello_world():
    return 'Hello World!'

@app.route('/login',methods=['get','post'])
def login():
    if request.method=='GET':
        return render_template('login.html')
    else:
        username=request.form.get('username')
        password=request.form.get('password')
        if username=='zjj' and password=='123':
            session['username']='zjj'
            return redirect('/home')
        else:
            return render_template('login.html',err='账号或密码错误')


@app.route('/home',endpoint='home')
@outer
def home():
    return render_template('home.html',user_dict=USERS)

@app.route('/detail/<int:pk>',endpoint='detail')
@outer
def detail(pk):
    user_detail=USERS.get(pk)
    return render_template('detail.html',info=user_detail)


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

新手四件套:

返回字符串  return '字符串'  -----》django中HttpResponse('字符串')
返回模板    return render_template-----》django中render(request,模板,{})
返回重定向  return redirect('/login')-----》django中return redirect('/login')
返回json   return jsonify(字典,列表)-----》django中JsonResponse

session的使用:

直接全局导入,使用即可 session['']=赋值

路由的分组出参数的使用:

@app.route('/detail/<int:pk>')
def detail(pk):
    pass

render_template的使用:

 render_template(模板名字,变量=值,变量=值)
        render(request,'模板名字',context={变量:值,变量:值})

取出post提交的数据:

request.form

login.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<form action="" method="post">
    <p>用户名:<input type="text" name="username"></p>
    <p>密码:<input type="password" name="password"></p>
    <input type="submit" value="提交">{{err}}
</form>

</body>
</html>

home.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
  <h1>用户列表</h1>
    <table>
        {% for k,v in user_dict.items() %}
        <tr>
            <td>{{k}}</td>
            <td>{{v.name}}</td>
            <td>{{v['name']}}</td>
            <td>{{v.get('name')}}</td>
            <td><a href="/detail/{{k}}">查看详细</a></td>
        </tr>
        {% endfor %}
    </table>
</body>
</html>

detail.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
   <h1>详细信息 {{info.name}}</h1>
    <div>
        {{info.text}}
    </div>
</body>
</html>

配置文件写法

# 项目的配置文件:如果不配,有默认的
# 几个重要的
DEBUG:是否是调试模式
SECRET_KEY:项目的秘钥
print(app.config)
# 1 使用配置文件之一:(写小脚本测试阶段用)直接通过app对象,配置上,只能配置几个,本质都要放到app.config中
app.debug=True
app.secret_key='asdfasf4555'
app.session_cookie_name='sss'
print(app.config)

# 2 直接通过app.config 配置
app.config['DEBUG'] = True
app.config['SECRET_KEY'] = 'asfasdf'
print(app.config)

# 3 通过配置文件(很像djagno),不常用
app.config.from_pyfile('settings.py')
print(app.config)

# 4 通过类配置(用的多,可以有多套配置)
app.config.from_object('setting.DevelopmentConfig')
app.config.from_object('setting.ProductionConfig')
print(app.config)

# 5 以下,做了解
app.config.from_envvar("环境变量名称")
app.config.from_json("json文件名称")

#使用分布式配置中心
import requests
res=requests.get('asdfasdfasdf').json()
app.config.from_mapping(res)
# 拓展:配置文件都在本地

路由系统

# flask 的路由系统,djagno中,路由是单独的urls.py,flask中是装饰的形式

# 使用方式
@app.route:重要的参数
    -rule: 字符串的路径,使用转换器  <string:name>  <name>
        'default':          UnicodeConverter,
        'string':           UnicodeConverter,
        'any':              AnyConverter,
        'path':             PathConverter,    # /xx/sss/
        'int':              IntegerConverter, # 数字
        'float':            FloatConverter,   #小数
        'uuid':             UUIDConverter,    #asdfas-asdfas-asdf
        #记住:string,int,path
    -methods: 列表,规定请求的方式,如果列表中没有,该请求方式不被支持
    -endpoint:路由别名,如果不写,会以被装饰的函数名作为别名,django中叫name

路由本质

# flask中路由是使用装饰器的,但是它的本质其实是app对象(Flask)的方法self.add_url_rule(rule, endpoint, f, **options)

# 如果在视图函数上加了装饰器,其实本质是在调用self.add_url_rule
    -我们可以不加装饰器,自己调用这个方法,也能完成路由的注册

# 路由本质:
'''
1 @app.route('/') 先执行完成,结果是decorator内层函数
    @decorator
    def index():
2 index=decorator(index)
    def decorator(f):
        # @app.route('/',endpoint='index') 如果没有传endpoint,这个地方就是None
        endpoint = options.pop("endpoint", None)
        # self是Flask的对象,app :rule路由, endpoint:别名,是None,其他的打散了传入了(methods..)
        self.add_url_rule(rule, endpoint, f, **options)
        return f
3 加了装饰器最终,返回的还是index,只不过执行了 self.add_url_rule(rule, endpoint, f, **options)

4 Flask类中得add_url_rule方法
    -rule:就是装饰器传入的路径,路由
    -endpoint:别名
    -view_func:视图函数不加括号

5 得到的结论,现在不需要使用装饰器来注册路由了,自己写
    app.add_url_rule('/home', view_func=home, endpoint='home')

'''

# 其实跟djagno没有大的差距,只是使用装饰器来配置

add_url_rule的参数

@app.route和app.add_url_rule参数:
# rule, URL规则
# view_func, 视图函数名称
# defaults = None, 默认值, 当URL中无参数,函数需要参数时,使用defaults = {'k': 'v'}
为函数提供参数,就是djagno中得kwargs

# endpoint = None, 名称,用于反向生成URL,即: url_for('名称'),等同于django的reverse
# methods = None, 允许的请求方式,如:["GET", "POST"]

# strict_slashes 对URL最后的 / 符号是否严格要求
strict_slashes = None
    '''
        @app.route('/index', strict_slashes=False)
        #访问http://www.xx.com/index/ 或http://www.xx.com/index均可
        @app.route('/index', strict_slashes=True)
        #仅访问http://www.xx.com/index
    '''
# redirect_to 重定向到指定地址
redirect_to = None, 
    '''
        @app.route('/index/<int:nid>', redirect_to='/home/<nid>')
    '''

cbv写法

flask 的cbv写法

# 第一步:写一个类,继承MethodView
    class Login(MethodView):
        def get(self):
            return '我是get'
        def post(self):
            return '我是psot'

# 第二步:注册路由 name 是别名,本质就是endpoint
    app.add_url_rule('/login', view_func=Login.as_view(name='index'))

# 第三步:只要向 /login 发送get请求,就会执行Login 的get方法

cbv加装饰器,如何做?

# 研究第0个问题:cbv加装饰器,如何做?
    类属性中加入,加入decorators = [auth, ],属性是一个列表,按照列表顺序,依次给每个方法加装饰器

     def as_view(cls, name, *class_args, **class_kwargs ) :
       ....
       if cls.decorators:
          for decorator in cls.decorators:
            '''
            # 装饰器原理:
             @auth
             def view():
             本质是  view=auth(view)
            '''
            # 给view加装饰器----》给视图类中得方法加装饰器
             view = decorator(view)
        return view

as_view的执行流程

# 研究第1个问题,as_view的执行流程
    def as_view(cls, name, *class_args, **class_kwargs):
        def view(**kwargs):
            return self.dispatch_request(**kwargs)
        return view

    -请求来了,路由匹配成功,会执行as_view内的view()----》self.dispatch_request---》MethodView的dispatch_request
    -MethodView的dispatch_request
      def dispatch_request(self, **kwargs):
        # 在当前视图类中反射,请求方式的小写字符串(get),我们写了get方法
        meth = getattr(self, request.method.lower(), None)
        # 执行get()
        return meth(**kwargs) 

Login.as_view(name='index') name到底有什么用

# 研究第2个问题:Login.as_view(name='index')  name到底有什么用,还必须传
    -先研究 endpoint 有什么用,正常的fbv,如果不写endpoint,会以函数名作为别名,endpoint如何设置的
    -如果endpoint为None,它把函数名作为了endpoint
      if endpoint is None:
            endpoint = _endpoint_from_view_func(view_func)# view_func.__name__
        options["endpoint"] = endpoint

   -Login.as_view(name='index'),name到底有啥用
        -app.add_url_rule('/login', view_func=Login.as_view('login'))
        -没有传endpoint,Login.as_view('login')是 view函数的内存地址,
        -endpoint会以函数名作为endpoint的值,现在所有函数都是view,必须传入name,来修改调view函数的名字
        -如果传了endpoint,别名以endpoint为主,如果不传endpoint,别名以name为主
        app.add_url_rule('/login', view_func=Login.as_view(name='login'),endpoint='xxx')

继承View写cbv

# 继承View写视图类(CBV)
    -1 继承 View 的视图类,执行流程都是一样的
    -2 请求来了,路由匹配成功,执行self.dispatch_request
    -3 self.dispatch_request 没有实现,直接抛异常NotImplementedError()
    -4 必须重写 dispatch_request,自己写匹配规则,执行不同的方法

cbv中得methods作用

# 视图类中还有个类属性 methods = ['POST']
    -用来控制允许的请求方式
    -如果不写,写了什么方法,就允许什么请求

模板语法

# dtl中得所有语法,它都支持,并且能够使用   函数()  可以传参数
from flask import Flask, render_template,Markup
app = Flask(__name__)
@app.route('/')
def index():
    # return render_template('test.html', name='lqz', age=19)
    # return render_template('test.html',
    #                        user={
    #                            1: {'name': 'lqz', 'age': 19, 'hobby': '篮球'},
    #                            2: {'name': 'lqz1', 'age': 20, 'hobby': '橄榄球'},
    #                            3: {'name': 'lqz2', 'age': 21, 'hobby': '乒乓球'},
    #                        })

    a='<a href="http://www.baidu.com">点我看美女</a>'
    # a=Markup(a)
    return render_template('test.html',a=a)
if __name__ == '__main__':
    app.run()

前端页面

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
{#{{ name }}---{{ age }}#}

{#<table>#}
{#    {% for k,v in user.items() %}#}
{#        <tr>#}
{#            <td>{{ k }}</td>#}
{#            <td>{{ v.name }}</td>#}
{#            <td>{{ v['name'] }}</td>#}
{#            <td>{{ v.get('name') }}</td>#}
{#            <td><a href="/detail/{{ k }}">查看详细</a></td>#}
{#        </tr>#}
{#    {% endfor %}#}
{#</table>#}

{#<table>#}
{#    {% if name %}#}
{#        <h1>Hello {{ name }}!</h1>#}
{#    {% else %}#}
{#        <h1>Hello World!</h1>#}
{#    {% endif %}#}
{#</table>#}

{#{{ a|safe }}#}
{{ a}}

</body>
</html>

标签:endpoint,return,name,flask,app,rule,view
From: https://www.cnblogs.com/wwjjll/p/16974574.html

相关文章

  • Flask框架
    Flask框架介绍flask是基于python开发并且依赖于jinjia2模板和werkzeugwsgi服务的一个微型框架werkzeug本质是socket服务端,用于接收http请求并对其进行预处理,然后触发......
  • vue无法获取flask设置的cookie
    最近在使用vue3开发基于flask后端的前后端分离项目时候,设置路由守卫时一直无法获取到登录后的cookie中session值但是在浏览器中却可以看到cookie先上代码router.befor......
  • flask-02
    一、web框架原理0、web框架简单说:就是请求对象和响应对象1、bs架构:B=浏览器、桌面端、小程序、app,   S=服务器2、最开始使用socket写一个服务端,接收的http请求,然后......
  • flask配置文件、路由、模板语法与cbv
    web框架原理1..符合wsgi协议1.1使用wsgiref写fromwsgiref.simple_serverimportmake_serverdefmya(environ,start_response):print(environ)#environ是ht......
  • flask蓝图与项目一般结构
    flask一般项目结构初始化配置flask项目时,路由和视图是放在启动文件里的,这样不太方便我们后期的整理和查阅!因此,我们需要将项目启动文件和路由视图分开处理!在项目文件下......
  • flask基础介绍和语法
    flask基础介绍和语法flask项目初始化的app.py介绍#从flask包中导入flask类fromflaskimportFlask#使用flask类实例化出一个app对象#__name__:代表当前app.py这......
  • 学习python-flask
    Flask介绍目前python界,比较出名的web框架django:大而全,web开发用的东西,它都有Flask:小而精,只能完成请求与响应,session,cache,orm,admin则都没有。可以用很多第三方框架,使......
  • 【Flask】flask应用
    目录1.配置文件写法2.路由系统3.路由本质3.1add_url_rule的参数4.cbv写法4.1flask的cbv写法4.2cbv加装饰器,如何做?4.3as_view的执行流程4.4Login.as_view(name='......
  • python flask 启动时报错如何解决ModuleNotFoundError: No module named 'flask._comp
    今天对flask项目的数据库脚本迁移做了些更改,发现项目启动时一直在报错   这是因为我使用的是高版本的flask和flask_migrate,flask_script中的一些模块在高版本中已......
  • flask_Mail谷歌邮箱发送邮件配置
    1、谷歌邮箱设置中打开转寄和POP/IMAP,选择启用IMAP2、谷歌账号开启两步认证3、设置应用密码4、flask新增邮件配置......