zoukankan      html  css  js  c++  java
  • flask入门

    1.入门程序

    from flask import Flask

    app = Flask(__name__)
    app.run()

    flask提供了自动重启服务的功能:调试模式

    app.run(debug=True)

    2.定义路由

    @route('/user/<username>')

    @route('/post/<int:uid>')

    @route('/post/<float:price>')

    @route('/post/<path:path>')

    路由装饰器:

        def route(self, rule, **options):
            """Like :meth:`Flask.route` but for a blueprint.  The endpoint for the
            :func:`url_for` function is prefixed with the name of the blueprint.
            """
            def decorator(f):
                endpoint = options.pop("endpoint", f.__name__)
                self.add_url_rule(rule, endpoint, f, **options)
                return f
            return decorator
    from flask import Flask

    app = Flask(__name__)

    # 视图函数
    @app.route("/hello/") -->/hello /hello/
    def hello():
    return "hello world"

    app.run()

    基于类的视图(即插视图)

    另一种注册路由的方式:app.add_url_rule("/hello", view_func=hello)

    @app.route和app.add_url_rule参数:
                rule,                       URL规则
                view_func,                  视图函数名称
                defaults=None,              默认值,当URL中无参数,函数需要参数时,使用defaults={'k':'v'}为函数提供参数
                endpoint=None,              名称,用于反向生成URL,即: url_for('名称')
                methods=None,               允许的请求方式,如:["GET","POST"]
                
    
                strict_slashes=None,        对URL最后的 / 符号是否严格要求,
                                            如:
                                                @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=None,           重定向到指定地址
                                            如:
                                                @app.route('/index/<int:nid>', redirect_to='/home/<nid>')
                                                或
                                                def func(adapter, nid):
                                                    return "/home/888"
                                                @app.route('/index/<int:nid>', redirect_to=func)
                subdomain=None,             子域名访问
                                                    from flask import Flask, views, url_for
    
                                                    app = Flask(import_name=__name__)
                                                    app.config['SERVER_NAME'] = 'wupeiqi.com:5000'
    
    
                                                    @app.route("/", subdomain="admin")
                                                    def static_index():
                                                        """Flask supports static subdomains
                                                        This is available at static.your-domain.tld"""
                                                        return "static.your-domain.tld"
    
    
                                                    @app.route("/dynamic", subdomain="<username>")
                                                    def username_index(username):
                                                        """Dynamic subdomains are also supported
                                                        Try going to user1.your-domain.tld/dynamic"""
                                                        return username + ".your-domain.tld"
    
    
                                                    if __name__ == '__main__':
                                                        app.run()

    反向构建URL

    <img src="{{ url_for('static', filename='/js/jquery.js') }}" />

    参数一:endpoint

    3.配置文件

    # 导入配置文件
    app.config.from_object('app.secure')
    app.config.from_object('app.setting')
    app.config['DEBUG']    --配置文件的变量必须大写
    
    在业务逻辑层使用配置文件:
      from flask import current_app
      current_app.config['KEY']
    
    

    4.返回结果

    4.1 json  【API】

    对于基本类型:

      return flask.jsonify(data)    

    对于对象类型:

      return json.dumps(obj, default=lambda o:o.__dict__)

     4.2 context-type:text/plain 返回纯文本

    from flask import make_response 
    # 默认 content-type:text/html
    # 返回response对象
    headers = {
    'content-type':'application/json',
    # 'content-type':'text/plain',
    'location':'www.baidu.com'
    }
    response = make_response("hello wolrdd", 200)
    response.headers = headers
    # return response
    # return 'hello flask', 200, headers

    4.3 返回带cookie的页面

    response = make_response(render_template('index.html'))
    # response是flask.wrappers.Response类型
    response.delete_cookie('key')
    response.set_cookie('key', 'value')
    response.headers['X-Something'] = 'A value'
    return response

    5.session

    session['k']=value
    # session.pop()

    6.将视图函数拆分多个文件中

    7.request参数

    7.1  url?q=xxx&page=xxx形式的参数,【get请求】

      通过request对象获取请求参数:

    from flask import request

    request.args['q']   或 request.args.get('q')

    request.args是不可变字典, 转化成可变字典:a = request.args.to_dict()

    7.2 form post

    request.form接受post请求参数

    7.3 URL方式接受参数

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

    8.WTFroms参数验证,验证层

    安装WTForms:pipenv install wtforms

    from wtforms import Form, StringField, IntegerField
    from wtforms.validators import Length, NumberRange, DataRequired
    
    
    class SearchForm(Form):
        # DataRequired要求参数不能为空格
        q = StringField(validators=[DataRequired(message='关键字不能为空格'), Length(min=1,max=30, message='关键字的长度应该在1-30')])
        page = IntegerField(validators=[NumberRange(min=1, max=20)], default=1)

     自定义验证器:

    业务需求:对邮箱进行验证,除了验证形式的合法性,还要验证数据库中是否存在

    class RegisterForm(Form):
        email = StringField(validators=[DataRequired(), Length(8, 64), Email(message='邮箱格式不合法')])
        password = StringField(validators=[DataRequired(message='密码不能为空'), Length(6,32)])
        nickname = StringField(validators=[DataRequired(), Length(2, 10, message='昵称长度2-10')])
    
        # 这个函数由WTForm自动调用,field为email属性
        def validate_email(self, field):
            if User.query.filter_by(email=field.data).first():
                raise ValidationError('电子邮箱已经被注册')   # 如果不合法,抛出指定的异常

    视图函数:

    from flask import Flask, make_response, jsonify, request
    
    from app.forms.book import SearchForm
    from . import web
    
    
    # 参数
    @web.route('/book/search', methods=['GET', 'POST'])
    def search():
        form = SearchForm(request.args)
        if form.validate():
            print('验证通过')
            q = form.q.data.strip()  #去空格
            page = form.page.data
            # 调用业务逻辑层
            result = {'q': q, 'page': page}
            return jsonify(result)
        else:
            print('验证失败')
            return jsonify(form.errors)

    9.数据库操作【ORM】 code first  sqlalchemy ->flask_SQLAlchemy

    安装flask_SQLAlchemy:pipenv install  flask-sqlalchemy

    安装数据库驱动:mysq->cymysql  或者pymysql

    from sqlalchemy import Column, Integer, String, Float
    
    
    class Book(object):
        id = Column(Integer, primary_key=True, autoincrement=True)
        title = Column(String(50), nullable=False)
        author = Column(String(20), nullable=False)
        price = Column(Float, nullable=True, default=0)
        isbn = Column(String(15), nullable=False, unique=True)
        summery = Column(String(200), default='没有简介')

    10.AppContext, RequestContext, Flask, Request关系【LocalProxy】

      

    12.模板渲染

    render(html, data)

    对于css、js文件,直接返回给客户端

    13.静态文件【css,js,images..】和 模板文件【HTML】

    Flask内部仍然使用路由、视图函数对静态文件进行返回。

    静态文件的默认位置:__name__/static

    模板文件的默认位置:__name__/templates

    修改默认位置:

    app = Flask(__name__, static_folder='view_model/static', templates_folder=' xxx ')  # 相对路径

    模板文件也可以放在蓝图下面:在蓝图的__init__文件,Blueprint('web', templates_folder=' xxx')

    14. 模板引擎:jinja2  【官网:http://jinja.pocoo.org/docs/2.10/

    14.1 基本设置

      为了让IDE【pycharm】更友好点(定位模板页面的路径),将对应文件夹设置为模板文件夹:

      设置模板引擎:

       实例:

    @web.route('/index', methods=['GET'])
    def index():
        data = {
            'name':'张三',
            'age':20
        }
        return render_template('index.html', data=data)

    对于字典和对象类型的data,可以使用点来访问,也可以使用索引

    <body>
    <div>
        <p>姓名:{{data.name}}</p>
        <p>年龄:{{data.age}}</p>
    </div>
    </body>

     字符串【raw】:默认字符串当做纯字符串

    {% set str='<input type="text">' %}
    {{ str }}

    如果需要HTML解析的字符串,在后台使用Markup(‘’)构造

    宏定义:

    {% macro xx(name, type='text', value='') %}
        <input type="{{ type }}" name="{{ name }}" value="{{ value }}" />
    {% endmacro %}
    {{ xx('age') }}

    14.2 流程控制语句

      所有的流程控制语句都要被包含在{%  %}内。

    (1)条件判断语句

    比较运算符、and 、or都可以使用

    {% if data.age < 20 %}
        {{ data.name }}
    {% elif data.age == 20 %}
         <p>年龄为 20</p>
    {% else %}
        <p>年龄大于20</p>
    {% endif %}

    (2)循环语句

    {% for i in range(5) %}
        <h3>{{ i }}</h3>
    {% endfor %}

    14.3 使用模板继承

    模板页:layout.html

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>鱼书</title>
    </head>
    <body>
        {% block head %}
            head
        {% endblock %}
        
        {% block content %}
        content {% endblock %} {% block foot %} footer {% endblock %}
    </body> </html>

    继承模板页:

    {% extends 'layout.html' %}
    
    {% block content %}
        {{ super() }}
        <p>姓名:{{data.name}}</p>
        <p>年龄:{{data.age}}</p>
        {% if data.age < 20 %}
            {{ data.name }}
        {% elif data.age == 20 %}
             <p>年龄为 20</p>
        {% else %}
            <p>年龄大于20</p>
        {% endif %}
    
        {% for i in range(5) %}
            <h3>{{ i }}</h3>
        {% endfor %}
    
    {% endblock %}

    14.4 过滤器【filter】

    default:

    {{ data.name | default('未名',False) }}     如果不存在name属性,显示未名,【异常处理】
    boolean=True => None,False, '', {}, [] -->default

    str = False or 'hello' ->hello
    str = None or 'hello' ->hello
    str = '' or 'hello' ->hello

     length:

     {{ data | length() }}     输出data的长度

     

    16.消息闪现

    @web.route('/index', methods=['GET'])
    def index():
        data = {
            'name':'张三',
            'age':20
        }
        flash('登录成功', category='ok')
        flash('成功进入系统', category='error')
        return render_template('index.html', data=data)

    使用消息:

      使用set定义的变量,作用域为blocks的全局变量

    {% set message = get_flashed_messages(category_filter='error') %}
    {{ message }}

     19.密码加密 【werkzeug.security】

     from werkzeug.security import generate_password_hash

    20.redirect重定向

    redirect(url_for('web.login'))   # 蓝图名.endpoint

    21.cookie

    response = make_response()

    response.set_cookie(key, value, timeout)

    flask提供了管理登录的插件:pipenv install flask_login     帮助文档

      login_user(user)  并不是将用户的所有信息都保存到cookie下,而是只需要保存用户的唯一标识ID。因此,在User类中需要定义一个方法get_id(self): return self.id

    或者让User继承UserMixin,该类提供了更多的登录相关的方法、属性。  

    访问权限控制:插件装饰器

    user.py

    @login_manager.user_loader
    def get_user(uid):
        return User.query.get(int(uid))

    gift.py

    @web.route('/my/gift')
    @login_required
    def my_gift():
        return 'my gift'
    @web.route('/login', methods=['GET', 'POST'])
    def login():
        form = LoginForm(request.form)
        if request.method == 'POST' and form.validate():
            user = User.query.filter_by(email=form.email.data).first()
    
            if user and user.check_password(form.password.data):
                # 使用登录管理器 管理登录
                login_user(user, remember=True)
                next = request.args.get('next')
                if not next or not next.startswith('/'):
                    next = url_for('web.index')
                return redirect(next)
            else:
                flash('账号不存在或者密码错误')
        return render_template('auth/login.html', form=form)
  • 相关阅读:
    eclipse中如何修改编码格式
    如何让Div中的Table居中
    EL表达式和标准标签库
    jQuery获取option的一些常用方法
    第三十五章——过滤器和监听器
    第三十四章——java web的注册登录和留言板的制作
    关于九大内置对象的补充——application
    第三十三章——javaweb初识和九大内置对象
    学习记录
    从 HTTP 到 HTTPS 再到 HSTS
  • 原文地址:https://www.cnblogs.com/zhuxiang1633/p/9304413.html
Copyright © 2011-2022 走看看