zoukankan      html  css  js  c++  java
  • Flask入门教程

    Flask基础教程

    1. 简介

    Flask是一个基于Python开发并且依赖jinja2模板和Werkzeug WSGI服务的一个微型框架,对于Werkzeug本质是Socket服务端,其用于接收http请求并对请求进行预处理,然后触发Flask框架,开发人员基于Flask框架提供的功能对请求进行相应的处理,并返回给用户,如果要返回给用户复杂的内容时,需要借助jinja2模板来实现对模板的处理,即:将模板和数据进行渲染,将渲染后的字符串返回给用户浏览器。

    “微”(micro) 并不表示你需要把整个 Web 应用塞进单个 Python 文件(虽然确实可以 ),也不意味着 Flask 在功能上有所欠缺。微框架中的“微”意味着 Flask 旨在保持核心简单而易于扩展。Flask 不会替你做出太多决策——比如使用何种数据库。而那些 Flask 所选择的——比如使用何种模板引擎——则很容易替换。除此之外的一切都由可由你掌握。如此,Flask 可以与您珠联璧合。

    默认情况下,Flask 不包含数据库抽象层、表单验证,或是其它任何已有多种库可以胜任的功能。然而,Flask 支持用扩展来给应用添加这些功能,如同是 Flask 本身实现的一样。众多的扩展提供了数据库集成、表单验证、上传处理、各种各样的开放认证技术等功能。Flask 也许是“微小”的,但它已准备好在需求繁杂的生产环境中投入使用。

    2. 基本使用

    from flask import Flask
    
    app = Flask(__name__)
    
    @app.route('/')
    
    def hello_world():
    
        return 'Hello World!'
    
    if __name__ == '__main__':
    
        app.run()
    flask 基本使用

    3. 配置文件

    flask中的配置文件是一个flask.config.Config对象(继承字典),默认配置为:

    {
        'DEBUG':False,
        'TESTING':False,
        'PROPAGATE_EXCEPTIONS': None,                          
        'PRESERVE_CONTEXT_ON_EXCEPTION': None,
        'SECRET_KEY': None,
        'PERMANENT_SESSION_LIFETIME': timedelta(days=31),
        'USE_X_SENDFILE': False,
        'LOGGER_NAME': None,
        'LOGGER_HANDLER_POLICY': 'always',
        'SERVER_NAME': None,
        'APPLICATION_ROOT': None,
        'SESSION_COOKIE_NAME': 'session',
        'SESSION_COOKIE_DOMAIN': None,
        'SESSION_COOKIE_PATH': None,
        'SESSION_COOKIE_HTTPONLY': True,
        'SESSION_COOKIE_SECURE': False,
        'SESSION_REFRESH_EACH_REQUEST': True,
        'MAX_CONTENT_LENGTH': None,
        'SEND_FILE_MAX_AGE_DEFAULT': timedelta(hours=12),
        'TRAP_BAD_REQUEST_ERRORS': False,
        'TRAP_HTTP_EXCEPTIONS': False,
        'EXPLAIN_TEMPLATE_LOADING': False,
        'PREFERRED_URL_SCHEME': 'http',
        'JSON_AS_ASCII': True,
        'JSON_SORT_KEYS': True,
        'JSONIFY_PRETTYPRINT_REGULAR': True,
        'JSONIFY_MIMETYPE': 'application/json',
        'TEMPLATES_AUTO_RELOAD': None,
    }

    方式一:

    app.config['DEBUG'] = True

    PS: 由于Config对象本质上是字典,所以还可以使用app.config.update(...)

    方式二:app.config.from_pyfile("python文件名称")

    settings.py

    DEBUG = True
    app.config.from_pyfile("settings.py")
    app.config.from_envvar("环境变量名称")

    环境变量的值为python文件名称名称,内部调用from_pyfile方法

    app.config.from_json("json文件名称")

    JSON文件名称,必须是json格式,因为内部会执行json.loads

    app.config.from_mapping({'DEBUG':True})

    字典格式

    app.config.from_object("python类或类的路径")
    app.config.from_object('pro_flask.settings.TestingConfig')

    settings.py

    class Config(object):
        DEBUG = False
        TESTING = False
        DATABASE_URI = 'sqlite://:memory:'
        
    class ProductionConfig(Config):
        DATABASE_URI = 'mysql://user@localhost/foo'
        
    class DevelopmentConfig(Config):
        DEBUG = True
        
    class TestingConfig(Config):
        TESTING = True

    PS: 从sys.path中已经存在路径开始写

    PS: settings.py文件默认路径要放在程序root_path目录,如果instance_relative_config 为True,则就是instance_path目录

    4. 路由系统

    1 @app.route('/user/<username>')
    3 @app.route('/post/<int:post_id>')
    5 @app.route('/post/<float:post_id>')
    7 @app.route('/post/<path:path>')
    9 @app.route('/login', methods=['GET', 'POST'])

    常用路由系统有以上五种,所有的路由系统都是基于一下对应关系来处理:

    DEFAULT_CONVERTERS = {
        'default':UnicodeConverter,
        'string':UnicodeConverter,
        'any':AnyConverter,
        'path':PathConverter,
        'int':IntegerConverter,
        'float':FloatConverter,
        'uuid':UUIDConverter,
    }

    4.1 注册路由原理

    def auth(func):
        def inner(*args, **kwargs):
            print('before')
            result = func(*args, **kwargs)
            print('after')
            return result
        return inner
    
    @app.route('/index.html', methods=['GET', 'POST'], endpoint='index')
    @auth
    def index():
        return 'Index' 

       

    def index():
        return "Index"
    self.add_url_rule(rule='/index.html', endpoint="index", view_func=index, methods=["GET","POST"])

    or

    app.add_url_rule(rule='/index.html', endpoint="index", view_func=index, methods=["GET","POST"])
    app.view_functions['index'] = index

    def auth(func):
        def inner(*args, **kwargs):
            print('before')
            result = func(*args, **kwargs)
            print('after')
            return result
        return inner
    
    class IndexView(views.View):
        methods = ['GET']
        decorators = [auth, ]
        def dispatch_request(self):
            print('Index')
            return 'Index!'
    app.add_url_rule('/index', view_func=IndexView.as_view(name='index'))  # name=endpoint 

    class IndexView(views.MethodView):
        methods = ['GET']
        decorators = [auth, ]
        def get(self):
            return 'Index.GET'
        def post(self):
            return 'Index.POST'
    app.add_url_rule('/index', view_func=IndexView.as_view(name='index'))  # name=endpoint

    @app.route和app.add_url_rule参数:

    1 rule,URL规则
    3 view_func, 视图函数名称
    5 defaults=None, 默认值,当URL中无参数,函数需要参数时,使用 defaults={'k':'v'}为函数提供参数
    7 endpoint=None, 名称,用于反向生成URL,即: url_for('名称')
    9 methods=None, 允许的请求方式,如:["GET","POST"]

    strict_slashes=None,对URL最后的 / 符号是否严格要求,

    如:

    1 @app.route('/index',strict_slashes=False),

    访问 http://www.xx.com/index/ 或 http://www.xx.com/index均可

    1 @app.route('/index',strict_slashes=True)

    仅访问 http://www.xx.com/index

    redirect_to=None,  重定向到指定地址

    如:

    1 @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()

    4.1 自定制正则路由匹配

    from flask import Flask, views, url_for
    from werkzeug.routing import BaseConverter
    app = Flask(import_name=__name__)
    class RegexConverter(BaseConverter):
        """
        自定义URL匹配正则表达式
        """
        def __init__(self, map, regex):
            super(RegexConverter, self).__init__(map)
            self.regex = regex
    
        def to_python(self, value):
            """
            路由匹配时,匹配成功后传递给视图函数中参数的值
            :param value:
            :return:
            """
            return int(value)
    
        def to_url(self, value):
            """
            使用url_for反向生成URL时,传递的参数经过该方法处理,返回的值用于生成 URL中的参数
            :param value:
            :return:
            """
            val = super(RegexConverter, self).to_url(value)
            return val
        
    # 添加到flask中
    app.url_map.converters['regex'] = RegexConverter
    @app.route('/index/<regex("d+"):nid>')
    def index(nid):
        print(url_for('index', nid='888'))
        return 'Index'
    if __name__ == '__main__':
        app.run()

    5. 模板

    1、模板的使用

    Flask使用的是Jinja2模板,所以其语法和Django无差别

    2、自定义模板方法

    Flask中自定义模板方法的方式和Bottle相似,创建一个函数并通过参数的形式传入 render_template,如:

    html:

    <!DOCTYPE html>
    <html>
    <head lang="en">
        <meta charset="UTF-8">
        <title></title>
    </head>
    <body>
        <h1>自定义函数</h1>
        {{ww()|safe}}
    </body>
    </html> 

    run.py:

    #!/usr/bin/env python
    # -*- coding:utf-8 -*-
    from flask import Flask,render_template
    app
    = Flask(__name__) def wupeiqi(): return '<h1>Wupeiqi</h1>'
    @app.route('/login', methods=['GET', 'POST']) def login(): return render_template('login.html', ww=wupeiqi)
    app.run()

    其他:

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
    </head>
    <body>
        {% macro input(name, type='text', value='') %}
            <input type="{{ type }}" name="{{ name }}" value="{{ value }}">
        {% endmacro %}
        {{ input('n1') }}
        {% include 'tp.html' %}
        <h1>asdf{{ v.k1}}</h1>
    </body>
    </html>

    6. 请求和响应

    from flask import request
    from flask import render_template
    from flask import redirect
    from flask import make_response
    app = Flask(__name__)
    
    @app.route('/login.html', methods=['GET', "POST"])
    def login():
        # 请求相关信息 =====================================================================
        # request.method
        # request.args
        # request.form
        # request.values
        # request.cookies
        # request.headers
        # request.path
        # request.full_path
        # request.script_root
        # request.url
        # request.base_url
        # request.url_root
        # request.host_url
        # request.host
        # request.files
        # obj = request.files['the_file_name']
        # obj.save('/var/www/uploads/' + secure_filename(f.filename))
    
        # 响应相关信息 ===================================================================
        # return "字符串"
        # return render_template('html模板路径',**{})
        # return redirect('/index.html')
        # 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
        return "内容"
    
    if __name__ == '__main__':
        app.run()

    7. Session

    除请求对象之外,还有一个 session 对象。它允许你在不同请求间存储特定用户的信息。 它是在 Cookies 的基础上实现的,并且对 Cookies 进行密钥签名要使用会话,你需要设 置一个密钥。

    1 设置:session['username'] = 'xxx'
    3 删除:session.pop('username', None)

    7.1 基本使用:

    from flask import Flask, session, redirect, url_for, escape, request
    
    app = Flask(__name__)
    @app.route('/')
    def index():
        if 'username' in session:
            return 'Logged in as %s' % escape(session['username'])
        return 'You are not logged in'
    
    @app.route('/login', methods=['GET', 'POST'])
    def login():
        if request.method == 'POST':
            session['username'] = request.form['username']
            return redirect(url_for('index'))
        return '''
            <form action="" method="post">
                <p><input type=text name=username>
                <p><input type=submit value=Login>
            </form>
        '''
    
    @app.route('/logout')
    def logout():
        # remove the username from the session if it's there
        session.pop('username', None)
        return redirect(url_for('index'))
    # set the secret key.  keep this really secret:
    app.secret_key = 'A0Zr98j/3yX R~XHH!jmN]LWX/,?RT'

    7.2 自定义Session

    1 pip3 install Flask-Session

    run.py:

    from flask import Flask
    from flask import session
    from pro_flask.utils.session import MySessionInterface
    app = Flask(__name__)
    app.secret_key = 'A0Zr98j/3yX R~XHH!jmN]LWX/,?RT'
    app.session_interface = MySessionInterface()
    @app.route('/login.html', methods=['GET', "POST"])
    def login():
        print(session)
        session['user1'] = 'alex'
        session['user2'] = 'alex'
        del session['user2']
        return "内容"
    if __name__ == '__main__':
        app.run() 

    session.py:

    import uuid
    import json
    import redis
    from flask.sessions import SessionInterface
    from flask.sessions import SessionMixin
    from itsdangerous import Signer, BadSignature, want_bytes
    
    
    class MySession(dict, SessionMixin):
        def __init__(self, initial=None, sid=None):
            self.sid = sid
            self.initial = initial
            super(MySession, self).__init__(initial or ())
    
        def __setitem__(self, key, value):
            super(MySession, self).__setitem__(key, value)
    
        def __getitem__(self, item):
            return super(MySession, self).__getitem__(item)
    
        def __delitem__(self, key):
            super(MySession, self).__delitem__(key)
    
    
    class MySessionInterface(SessionInterface):
        session_class = MySession
        container = {}
    
        def __init__(self):
            self.redis = redis.Redis()
    
        def _generate_sid(self):
            return str(uuid.uuid4())
    
        def _get_signer(self, app):
            if not app.secret_key:
                return None
            return Signer(app.secret_key, salt='flask-session', key_derivation='hmac')
    
        def open_session(self, app, request):
            """
            程序刚启动时执行,需要返回一个session对象
            """
            sid = request.cookies.get(app.session_cookie_name)
            if not sid:
                sid = self._generate_sid()
                return self.session_class(sid=sid)
                signer = self._get_signer(app)
                try:
                    sid_as_bytes = signer.unsign(sid)
                    sid = sid_as_bytes.decode()
                except BadSignature:
                    sid = self._generate_sid()
                    return self.session_class(sid=sid)
    
        # session保存在redis中
        # val = self.redis.get(sid)
        # session保存在内存中
        val = self.container.get(sid)
        if val is not None:
            try:
                data = json.loads(val)
                return self.session_class(data, sid=sid)
            except:
                return self.session_class(sid=sid)
                return self.session_class(sid=sid)
    
    
    def save_session(self, app, session, response):
        """
        程序结束前执行,可以保存session中所有的值
        如:
        保存到resit
        写入到用户cookie
        """
        domain = self.get_cookie_domain(app)
        path = self.get_cookie_path(app)
        httponly = self.get_cookie_httponly(app)
        secure = self.get_cookie_secure(app)
        expires = self.get_expiration_time(app, session)
        val = json.dumps(dict(session))
        # session保存在redis中
        # self.redis.setex(name=session.sid, value=val, time=app.permanent_session_lifetime)
        # session保存在内存中
        self.container.setdefault(session.sid, val)
        session_id = self._get_signer(app).sign(want_bytes(session.sid))
        response.set_cookie(app.session_cookie_name, session_id,expires=expires, httponly=httponly,domain=domain, path=path, secure=secure)
    View Code

    7.3 第三方Session

    #!/usr/bin/env python
    
    # -*- coding:utf-8 -*-
    """
    pip3 install redis
    pip3 install flask-session
    """
    from flask import Flask, session, redirect
    from flask.ext.session import Session
    app = Flask(__name__)
    app.debug = True
    app.secret_key = 'asdfasdfasd'
    app.config['SESSION_TYPE'] = 'redis'
    from redis import Redis
    app.config['SESSION_REDIS'] = Redis(host='192.168.0.94',port='6379')
    Session(app)
    @app.route('/login')
    def login():
        session['username'] = 'alex'
        return redirect('/index')
    
    @app.route('/index')
    def index():
        name = session['username']
        return name
    
    if __name__ == '__main__':
    
        app.run()

    8. 蓝图

    蓝图用于为应用提供目录划分:

    8.1 小型应用程序:示例

    目录结构:

    run.py:详细代码:

    from pro_flask import app
    if __name__ == '__main__':
        app.run()

    __init__.py:

    #!/usr/bin/env python
    # -*- coding:utf-8 -*-
    from flask import Flask
    from .views.account import account
    from .views.blog import blog
    from .views.user import user
    
    app=Flask(__name__,template_folder='templates',static_folder='statics',static_url_path='/static')
    app.register_blueprint(account)
    app.register_blueprint(blog)
    app.register_blueprint(user)

    Account.py:

    #!/usr/bin/env python
    # -*- coding:utf-8 -*-
    from flask import Blueprint
    from flask import render_template
    from flask import request
    account = Blueprint('account', __name__)
    @account.route('/login.html', methods=['GET', "POST"])
    def login():
        return render_template('login.html')

    Blog.py:

    #!/usr/bin/env python
    # -*- coding:utf-8 -*-
    from flask import Blueprint
    blog = Blueprint('blog', __name__)

    User.py

    #!/usr/bin/env python
    # -*- coding:utf-8 -*-
    from flask import Blueprint
    user = Blueprint('user', __name__)

    Login.html

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
    </head>
    <body>
    <h1>用户登录</h1>
    <form method="POST">
        <input type="text" name="user"/>
        <input type="submit" value="提交"/>
    </form>
    <img src="/static/code.png">
    <img src="{{ url_for('static',filename='code.png') }}">
    </body>
    </html>

    8.2 大型应用程序:示例

    目录结构:

    详细代码:

    Run.py:

    from pro_flask import app
    if __name__ == '__main__':
        app.run() 

    __init__.py:

    #!/usr/bin/env python
    # -*- coding:utf-8 -*-
    from flask import Flask
    from .admin import admin
    from .web import web
     
    app = Flask(__name__)
    app.debug = True
    app.register_blueprint(admin, url_prefix='/admin')
    app.register_blueprint(web) 

    Admin/__init__.py:

    #!/usr/bin/env python
    # -*- coding:utf-8 -*-
    from flask import Blueprint
    admin = Blueprint('admin',__name__,template_folder='templates',static_folder='static')
    from . import views

    Admin/views.py:

    #!/usr/bin/env python
    # -*- coding:utf-8 -*-
    from . import admin
    @admin.route('/index')
    def index():
        return 'Admin.Index'

    Web/__init.py:

    #!/usr/bin/env python
    # -*- coding:utf-8 -*-
    from flask import Blueprint
    web = Blueprint('web',__name__,template_folder='templates',static_folder='static')
    from . import views

    Web/views.py:

    #!/usr/bin/env python
    # -*- coding:utf-8 -*-
    from . import web
    @web.route('/index')
    def index():
        return 'Web.Index'

    8.3 其他:

    蓝图URL前缀:xxx = Blueprint('account', __name__,url_prefix='/xxx')

    蓝图子域名:xxx = Blueprint('account', __name__,subdomain='admin')

    # 前提需要给配置SERVER_NAME: app.config['SERVER_NAME'] = 'wupeiqi.com:5000'

    # 访问时:admin.wupeiqi.com:5000/login.html

    9.  Message

    message是一个基于Session实现的用于保存数据的集合,其特点是:使用一次就删除。

    from flask import Flask, flash, redirect, render_template, request, get_flashed_messages
    app = Flask(__name__)
    app.secret_key = 'some_secret'
    @app.route('/')
    def index1():
      messages = get_flashed_messages()
      print(messages)
      return "Index1"
    
    @app.route('/set')
    def index2():
      v = request.args.get('p')
      flash(v)
      return 'ok'
    
    if __name__ == "__main__":
      app.run()

    10. 中间件

    from flask import Flask, flash, redirect, render_template, request
    app = Flask(__name__)
    app.secret_key = 'some_secret'

    @app.route('/') def index1(): return render_template('index.html') @app.route('/set') def index2(): v = request.args.get('p') flash(v) return 'ok' class MiddleWare: def __init__(self,wsgi_app): self.wsgi_app = wsgi_app
    def __call__(self, *args, **kwargs): return self.wsgi_app(*args, **kwargs) if __name__ == "__main__": app.wsgi_app = MiddleWare(app.wsgi_app) app.run(port=9999)

    11. 请求扩展

    #!/usr/bin/env python
    # -*- coding:utf-8 -*-
    from flask import Flask, Request, render_template
    app = Flask(__name__, template_folder='templates')
    app.debug = True
    
    @app.before_first_request
    def before_first_request1():
        print('before_first_request1')
    
    @app.before_first_request
    def before_first_request2():
        print('before_first_request2')
    
    @app.before_request
    def before_request1():
        Request.nnn = 123
        print('before_request1')
    
    @app.before_request
    def before_request2():
        print('before_request2')
    
    @app.after_request
    def after_request1(response):
        print('before_request1', response)
        return response
    
    @app.after_request
    def after_request2(response):
        print('before_request2', response)
        return response
     
    @app.errorhandler(404)
    def page_not_found(error):
        return 'This page does not exist', 404
     
    @app.template_global()
    def sb(a1, a2):
        return a1 + a2
     
    @app.template_filter()
    def db(a1, a2, a3):
        return a1 + a2 + a3
    
    @app.route('/')
    def hello_world():
        return render_template('hello.html')
     
    if __name__ == '__main__':
        app.run()

    调用方式:{{sb(1,2)}}  {{ 1|db(2,3)}}

    12. Flask插件

    12.1 WTForms

    简介:

    WTForms是一个支持多个web框架的form组件,主要用于对用户请求数据进行验证。

    简单使用:

    安装:pip install wtforms

    demo1(用户登录)

    app.pyfrom flask import Flask, render_template, request, redirect

    from wtforms import Form
    from wtforms.fields import simple
    from wtforms import validators
    from wtforms import widgets
    app = Flask(__name__, template_folder='templates')
    app.debug = True
    class LoginForm(Form):
      name = simple.StringField(label='用户名',
        validators=[
          validators.DataRequired(message='用户名不能为空.'),
          validators.Length(min=6, max=18, message='用户名长度必须大于%(min)d且小于%(max)d')
        ],
        widget=widgets.TextInput(),
        render_kw={'class': 'form-control'}
      )
      pwd = simple.PasswordField(
        label='密码',
        validators=[
          validators.DataRequired(message='密码不能为空.'),
          validators.Length(min=8, message='用户名长度必须大于%(min)d'),
          validators.Regexp(regex="^(?=.*[a-z])(?=.*[A-Z])(?=.*d)(?=.*[$@$!%*?&])[A-Z    a-zd$@$!%*?&]{8,}",message='密码至少8个字符,至少1个大写字母,1个    小写字母,1个数字和1个特殊字符')
        ],
        widget=widgets.PasswordInput(),
        render_kw={'class': 'form-control'}
      )
    @app.route('/login', methods=['GET', 'POST'])
    def login():
      if request.method == 'GET':
        form = LoginForm()
        return render_template('login.html', form=form)
      else:
        form = LoginForm(formdata=request.form)
        if form.validate():
          print('用户提交数据通过格式验证,提交的值为:', form.data)
        else:
          print(form.errors)
      return render_template('login.html', form=form)
    if __name__ == '__main__':   app.run()

    login.html

    <!DOCTYPE html>
    <html lang="en">
    <head>
    <meta charset="UTF-8">
    <title>Title</title>
    </head>
    <body>
    <h1>登录</h1>
    <form method="post">
    <!--<input type="text" name="name">-->
    <p>{{form.name.label}} {{form.name}} {{form.name.errors[0] }}</p>
    <!--<input type="password" name="pwd">-->
    <p>{{form.pwd.label}} {{form.pwd}} {{form.pwd.errors[0] }}</p>
    <input type="submit" value="提交">
    </form>
    </body>
    </html>

    demo2(用户注册):

    app.py

    from flask import Flask, render_template, request, redirect
    from wtforms import Form
    from wtforms.fields import core
    from wtforms.fields import html5
    from wtforms.fields import simple
    from wtforms import validators
    from wtforms import widgets
    app = Flask(__name__, template_folder='templates')
    app.debug = True
    class RegisterForm(Form):
      name = simple.StringField(
        label='用户名',
        validators=[
          validators.DataRequired()
        ],
        widget=widgets.TextInput(),
        render_kw={'class': 'form-control'},
        default='alex'
      )
    
      pwd = simple.PasswordField(
        label='密码',
        validators=[
          validators.DataRequired(message='密码不能为空.')
        ],
        widget=widgets.PasswordInput(),
        render_kw={'class': 'form-control'}
      )
    
      pwd_confirm = simple.PasswordField(
        label='重复密码',
        validators=[
          validators.DataRequired(message='重复密码不能为空.'),
          validators.EqualTo('pwd', message="两次密码输入不一致")
        ],
        widget=widgets.PasswordInput(),
        render_kw={'class': 'form-control'}
      )
    
      email = html5.EmailField(
        label='邮箱',
        validators=[
          validators.DataRequired(message='邮箱不能为空.'),
          validators.Email(message='邮箱格式错误')
        ],
        widget=widgets.TextInput(input_type='email'),
        render_kw={'class': 'form-control'}
      )
    
      gender = core.RadioField(
        label='性别',
        choices=((1, ''),(2, ''),),
        coerce
    =int   )   city = core.SelectField(     label='城市',     choices=(('bj', '北京'),('sh', '上海'),)   )   hobby = core.SelectMultipleField(     label='爱好',     choices=((1, '篮球'),(2, '足球'),),     coerce=int   )
      favor
    = core.SelectMultipleField(     label='喜好',     choices=((1, '篮球'),(2, '足球'),),     widget=widgets.ListWidget(prefix_label=False),     option_widget=widgets.CheckboxInput(),     coerce=int,     default=[1, 2]   )
    def __init__(self, *args, **kwargs):   super(RegisterForm, self).__init__(*args, **kwargs)   self.favor.choices = ((1, '篮球'), (2, '足球'), (3, '羽毛球')) def validate_pwd_confirm(self, field):   """   自定义pwd_confirm字段规则,例:与pwd字段是否一致   :param field:   :return:   """   # 最开始初始化时,self.data中已经有所有的值   if field.data != self.data['pwd']:     # raise validators.ValidationError("密码不一致") # 继续后续验证     raise validators.StopValidation("密码不一致") # 不再继续后续验证 @app.route('/register', methods=['GET', 'POST']) def register():   if request.method == 'GET':     form = RegisterForm(data={'gender': 1})     return render_template('register.html', form=form)   else:     form = RegisterForm(formdata=request.form)     if form.validate():       print('用户提交数据通过格式验证,提交的值为:', form.data)     else:       print(form.errors)       return render_template('register.html', form=form) if __name__ == '__main__':   app.run()

    register.html

    <!DOCTYPE html>
    <html lang="en">
      <head>
        <meta charset="UTF-8">
        <title>Title</title>
       </head>
    <body>
      <h1>用户注册</h1>
      <form method="post" novalidate style="padding:0  50px">
        {% for item in form %}
          <p>{{item.label}}: {{item}} {{item.errors[0] }}</p>
        {% endfor %}
        <input type="submit" value="提交">
      </form>
    </body>
    </html>

    如何实现:

    源码流程:

    1 解释:metaclass
    3 实例:form = LoginForm
    5 验证:form.validate()

    12.2 SQLAchemy

    SQLAlchemy项目基础实例

    项目结构:

     __init__.py

    from flask import Flask
    from flask_sqlalchemy import SQLAlchemy
    from .views.admin import admin
    from .views.shop import shop
    db = SQLAlchemy()
    from .models import  *
    def create_app():
      app = Flask(__name__, template_folder='templates', static_folder='statics', static_url_path='/static')
      # 导入配置文件(以类的形式导入)
      app.config.from_object("settings.TsetSesstings")
      # 将db注册到app中(在内部读取配置文件)      db.init_app(app)
      #注册蓝图      
      app.register_blueprint(admin)
      app.register_blueprint(shop)
      return app

    run.py

    # 程序入口from flask_app import create_app
    app = create_app()
    if __name__ == '__main__':
        app.run()

    settings.py

    # 这是配置文件
    # 测试配置
    class TsetSesstings():
        DEBUG = True
        TESTING = True
        SECRET_KEY = "djcishcnieodkscj9codscojsojcd0ojc"
        '''
        数据库连接配置
        SQLALCHEMY_DATABASE_URI', 'sqlite:///:memory:'
        SQLALCHEMY_BINDS', None
        SQLALCHEMY_NATIVE_UNICODE', None
        SQLALCHEMY_ECHO', False
        SQLALCHEMY_RECORD_QUERIES', None
        SQLALCHEMY_POOL_SIZE', None
        SQLALCHEMY_POOL_TIMEOUT', None
        SQLALCHEMY_POOL_RECYCLE', None
        SQLALCHEMY_MAX_OVERFLOW', None
        SQLALCHEMY_COMMIT_ON_TEARDOWN', False
        '''
        SQLALCHEMY_DATABASE_URI = 'mysql+pymysql://root:密码@localhost:3306/数据库名'
        SQLALCHEMY_POOL_SIZE = 5
        SQLALCHEMY_POOL_TIMEOUT = 30
        SQLALCHEMY_POOL_RECYCLE = -1
        # 追踪对象的修改并且发送信号
        SQLALCHEMY_TRACK_MODIFICATIONS = False
    
    # 正式配置
    class FormalSettings():
        DEBUG = False
        TESTING = False
        SECRET_KEY = "xfsec@admin!2019(shuijizifuchuan)"
        #数据库连接
      SQLALCHEMY_DATABASE_URI = 'mysql+pymysql://root:密码@localhost:3306/数据库名'
      SQLALCHEMY_POOL_SIZE = 5 
      SQLALCHEMY_POOL_TIMEOUT = 30 
      SQLALCHEMY_POOL_RECYCLE = -1 
      # 追踪对象的修改并且发送信号 
      SQLALCHEMY_TRACK_MODIFICATIONS = False

    models.py

    from . import db
    class Users1(db.Model):
        __tablename__ = "users"
        id  = db.Column(db.Integer,primary_key=True)
        username = db.Column(db.String(50),nullable=False,unique=True)
        email = db.Column(db.String(150), nullable=False, unique=True)
        def __repr__(self):
            return "<Users %r>" %self.username

    crcate_tables.py 

    # 这是一个创建数据库表的脚本
    
    from flask_app import db
    from flask_app import create_app
    app = create_app()
    with app.app_context():
    db.create_all()

    admin.py 

    from flask import Blueprint
    from flask import render_template
    from flask import request
    # 创建app应用
    # url_prefix : 路由拼接
    # template_folder : 模板路径
    admin= Blueprint('admin', __name__, url_prefix='/admin', template_folder='templates')
     
    # 每次请求进来时的操作
    @admin.before_request
    def process_request(*args, **kwargs):
      '''
      判断用户是否登陆
      '''
      if request.path == "/admin_dingding_xfsec/login":
        print("登录页面不需要登陆!!!")
        return None
      else:
        print("后台每次请求进来时都会执行这个函数")
    
    #每次请求结束时的操作(必须加return 否则会报错!!!)
    @admin.after_request
    def process_response(response):
      print("后台每次请求结束后都会执行这个函数")
      return response
    
    @admin.route('/login', methods=['GET', "POST"])
    def login():
      if request.method == "GET":
        return "前端登录页面!!!"
      else:
        pass
    
    @admin.route('/index', methods=['GET', "POST"])
    def index():
      if request.method == "GET":
        return "前端首页!!!"
      else:
        pass

    shop.py

    from flask import Blueprintfrom flask import render_templatefrom flask import request
    '''
    前端管理函数处理
    使用蓝图
    创建蓝图实例
    创建路由
    函数处理
    ''' shop = Blueprint('shop', __name__, template_folder='templates') # 每次请求进来时的操作 @shop.before_requestdef process_request(*args, **kwargs): print("前端每次请求进来时都会执行这个函数") # 每次请求结束时的操作(必须加return 否则会报错!!!) @shop.after_requestdef process_response(response): print("前端每次请求结束后都会执行这个函数") return response @shop.route('/login', methods=['GET', "POST"])def login(): if request.method == "GET":   return "前端登录页面!!!" else:   pass @shop.route('/index', methods=['GET', "POST"])def index(): if request.method == "GET":   return "前端首页!!!" else:   pass

    等...    http://flask.pocoo.org/extensions/

     

  • 相关阅读:
    win7(64bit)python相关环境模块搭建
    memcached在windows下的安装与命令使用方法
    pomelo流程
    pomelo 初始化配置...
    pomelo组件..
    <转>如何高效快速看懂Android源码
    源码学习
    计划
    Android面试题集锦 (转)
    Android 面试题(转)
  • 原文地址:https://www.cnblogs.com/xingxingnbsp/p/12397155.html
Copyright © 2011-2022 走看看