zoukankan      html  css  js  c++  java
  • Web框架之Flask

    Flask简介

    Flask是一个基于Python开发并且依赖jinja2模板和Werkzeug WSGI服务的一个微型框架,对于Werkzeug本质是Socket服务端,其用于接收http请求并对请求进行预处理,然后触发Flask框架,开发人员基于Flask框架提供的功能对请求进行相应的处理,并返回给用户,如果要返回给用户复杂的内容时,需要借助jinja2模板来实现对模板的处理,即:将模板和数据进行渲染,将渲染后的字符串返回给用户浏览器。
    
    “微”(micro) 并不表示你需要把整个 Web 应用塞进单个 Python 文件(虽然确实可以 ),也不意味着 Flask 在功能上有所欠缺。微框架中的“微”意味着 Flask 旨在保持核心简单而易于扩展。Flask 不会替你做出太多决策——比如使用何种数据库。而那些 Flask 所选择的——比如使用何种模板引擎——则很容易替换。除此之外的一切都由可由你掌握。如此,Flask 可以与您珠联璧合。
    
    默认情况下,Flask 不包含数据库抽象层、表单验证,或是其它任何已有多种库可以胜任的功能。然而,Flask 支持用扩展来给应用添加这些功能,如同是 Flask 本身实现的一样。众多的扩展提供了数据库集成、表单验证、上传处理、各种各样的开放认证技术等功能。Flask 也许是“微小”的,但它已准备好在需求繁杂的生产环境中投入使用。
    View Code

    安装

    pip install flask  
    from werkzeug.wrappers import Request, Response
    
    @Request.application
    def hello(request):
        return Response('Hello World!')
    
    if __name__ == '__main__':
        from werkzeug.serving import run_simple
        run_simple('localhost', 4000, hello)
    werkzeug

    一 基本使用

    from flask import Flask
    app = Flask(__name__)
     
    @app.route('/',methods=["GET","POST"]) 
      def hello_world():
        return 'Hello World!'

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

      

    二 配置文件

    flask中的配置文件是一个flask.config.Config对象(继承字典),默认配置为:
        {
            'DEBUG':                                get_debug_flag(default=False),  是否开启Debug模式
            '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目录
    

      

    三 路由系统

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

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

    DEFAULT_CONVERTERS = {
        'default':          UnicodeConverter,
        'string':           UnicodeConverter,
        'any':              AnyConverter,
        'path':             PathConverter,
        'int':              IntegerConverter,
        'float':            FloatConverter,
        'uuid':             UUIDConverter,
    }
    
    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参数:
                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()
            
    参数说明
    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 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()
    自定制正则路由匹配

    四 模版

    1、模板的使用

    在根目录下创建文件夹templates

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

    2、自定义模板方法

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

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>首页</title>
    </head>
    <body>
    
    <h1>{{msg}}</h1>
    
    <h1>循环</h1>
    {% for i in lis %}
    姓名{{i.name}}
    年龄{{i.age}}
    {% endfor %}
    
    
    <h1>自定义函数</h1>
    {{ func('n1') }}
    
    </body>
    </html>
    模版
    from flask import Flask,Response,redirect,render_template,request,Markup
    
    app = Flask(__name__)
    
    def func(x):
        print(x,"n1") #n1
        return Markup('<input value="www.baidu.com">百度</input>')
    
    
    @app.route('/index/',methods=["GET"])
    def index():
        if request.method=="GET":
            return render_template('index.html',**{'msg':666,"lis":[{"name":"zhou","age":18}],'func':func})
    
    
    
    if __name__ == '__main__':
        app.run()
    View
    <!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>
    其他

    注意:Markup等价django的mark_safe

    在模版中引入静态文件

    <script src="{{ url_for('static',filename='jquery-3.3.1.min.js')}}"></script>
    
    app = Flask(__name__,template_folder="templates",static_folder="static/js",static_url_path="/static/js")
    # static_folder 是模版渲染时查找的静态文件  static_url_path 是在浏览器访问静态文件地址
    

      

    五 请求与响应

    from flask import Flask
        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')
         # return Response()
         # return jsonify() 返回json数据
    # 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()

      

    六  Session 

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

    -  app.secret_key = "xxxxx"

    • 设置:session['username'] = 'xxx'

    • 删除:session.pop('username', None)

    在对session嵌套对内部做操作时,记得修改参数

    session.modified = True
    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'
    基本使用

    自定义session

    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
                #!/usr/bin/env python
                # -*- coding:utf-8 -*-
                import uuid
                import json
                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):
                        import redis
                        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)
    自定义Session

    第三方session

    from flask import Flask,session
    from redis import Redis
    
    # RedisSessionInterface, 
    #     MemcachedSessionInterface, FileSystemSessionInterface, 
    #     MongoDBSessionInterface, SqlAlchemySessionInterface
    
    
    app = Flask(__name__)
    app.secret_key = 'suijksdfsd'
    
    
    # 方式一
    from flask_session import RedisSessionInterface
    conn = Redis(host="0.0.0.0",port=6379)
    app.session_interface = RedisSessionInterface(conn,key_prefix='__',use_signer=False,permanent=True)
    # use_signer=False 不使用签名加密 ,permanent如果是False关闭浏览器cookie就失效
    
    # 方式二
    from flask.ext.session import Session
    app.config['SESSION_TYPE'] = 'redis'
    app.config['SESSION_REDIS'] = Redis(host="0.0.0.0",port=6379)
    Session(app)
    
    
    
    @app.route('/login/')
    def login():
        session['xxx'] = 123
        return 'login'
    @app.route("/")
    def index():
        print(session.get("xxx"))
        return "index"
    
    if __name__ == '__main__':
    
        app.run()
    flask_session

    七 message(闪现)

    from flask import Flask, flash, request, get_flashed_messages
    
    app = Flask(__name__)
    app.secret_key = 'some_secret' # 因为基于session,必须要设置该参数
    
    
    @app.route('/')
    def index1():
        messages = get_flashed_messages() # 一次性全取到,一个列表,只能取一次
        print(messages) # ['zhoujunhao', 'www']
        return "Index1"
    
    @app.route('/index/')
    def index3():
        flash("zhoujunhao")
        return "ok3"
    
    @app.route('/set/')
    def index2():
        v = request.args.get('p')
        flash("www")
        return 'ok2'
    
    
    if __name__ == "__main__":
        app.run()
    View Code

    八  请求扩展

    a. before_request 请求之前做的事

    a. 基于before_request做用户登录认证
        @app.before_request
        def process_request(*args,**kwargs):
            if request.path == '/login':
                return None  # 返回None代表通过,如果有返回值就不走视图直接返回
            user = session.get('user_info')
            if user:
                return None
            return redirect('/login')

    b. after_request 返回时做的事

    @app.after_request
    def process_response(response,*args,**kwargs):
        print("走了")
        return response  # 返回什么页面显示什么
    

    c. 执行顺序  和django 1.7 1.8 1.9 一样 process_request中如果有返回值,从最后一个process_response依次返回

    from flask import Flask, render_template, request, redirect, session, url_for
    
    app = Flask(__name__)
    app.debug = True
    app.secret_key = 'siuljskdjfs'
    
    
    @app.before_request
    def process_request1(*args, **kwargs):
        print('process_request1 进来了')
        return "lanjie"
    
    
    @app.before_request
    def process_request2(*args, **kwargs):
        print('process_request2 进来了')
    
    
    @app.after_request
    def process_response1(response):
        print('process_response1 走了')
        return response
    
    
    @app.after_request
    def process_response2(response):
        print('process_response2 走了')
        return response
    
    
    @app.route('/index/', methods=['GET'])
    def index():
        print('index函数')
        return "Index"
    
    
    if __name__ == '__main__':
        app.run()
    
    # process_request1 进来了
    # process_response2 走了
    # process_response1 走了
    

    d. 错误页面定制

    @app.errorhandler(404)
    def error_404(arg):
        print(arg) # 错误信息
        return "404错误了"
    

    e.  模版中定制方法

    @app.template_global()
    def sb(a1, a2):
        return a1 + a2
    {{sb(1,2)}}  
    
    
    @app.template_filter()
    def db(a1, a2, a3):
        return a1 + a2 + a3
    {{ 1|db(2,3)}} # 把|前面的值当做第一个参数传入
    

    f. before_first_request  第一次请求时执行

    @app.before_first_request # 只有第一次请求时执行
    def first(*args,**kwargs):
        print("进来了")
        return None
    

    九  中间件

    class MyMiddleWare(object):
        def __init__(self,old_wsgi_app):
            self.old_wsgi_app = old_wsgi_app
    
        def __call__(self, environ, start_response):
            print("开始之前")
            ret =  self.old_wsgi_app(environ, start_response)
            print("结束之后")
            return ret
    
    
    
    if __name__ == '__main__':
        # 把原来的app.wsgi_app当做参数传入自定制的类,得到一个对象赋值给app.wsgi_app,
        # 当调用app.wsgi_app时触发Md的__call__方法,在内部又执行了原有的操作,但是在执行前后可以添加一些操作
        app.wsgi_app = MyMiddleWare(app.wsgi_app)
        app.run()

      

    十  蓝图 blueprint

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

    小型应用:

     

    大型应用程序:

    其他:
    
    蓝图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

    十一  多App应用

    from werkzeug.wsgi import DispatcherMiddleware
    from werkzeug.serving import run_simple
    from flask import Flask
    
    app1 = Flask('app01')
    
    app2 = Flask('app02')
    
    
    
    @app1.route('/index')
    def index():
        return "app01"
    
    
    @app2.route('/index2')
    def index2():
        return "app2"
    
    # http://www.oldboyedu.com/index
    # http://www.oldboyedu.com/sec/index2
    dm = DispatcherMiddleware(app1, {
        '/sec': app2,
    })
    
    if __name__ == "__main__":
        run_simple('localhost', 5000, dm)

     源码

    class DispatcherMiddleware(object):
    
        """Allows one to mount middlewares or applications in a WSGI application.
        This is useful if you want to combine multiple WSGI applications::
    
            app = DispatcherMiddleware(app, {
                '/app2':        app2,
                '/app3':        app3
            })
        """
    
        def __init__(self, app, mounts=None):
            self.app = app
            self.mounts = mounts or {}
    
        def __call__(self, environ, start_response):
            script = environ.get('PATH_INFO', '')
            path_info = ''
            while '/' in script:
                if script in self.mounts:
                    app = self.mounts[script]
                    break
                script, last_item = script.rsplit('/', 1)
                path_info = '/%s%s' % (last_item, path_info)
            else:
                app = self.mounts.get(script, self.app)
            original_script_name = environ.get('SCRIPT_NAME', '')
            environ['SCRIPT_NAME'] = original_script_name + script
            environ['PATH_INFO'] = path_info
            return app(environ, start_response) # 最终还是调用了app的__call__()方法

    Flask-SQLAlchemy 

    下载地址:https://pan.baidu.com/s/1Lu_Na2sCRM7Fc1JrZaQcMg

    Flask-Script

    安装

    pip install flask-script

    使用

    from flask import Flask
    from flask_script import Manager
    
    
    app = Flask(__name__)
    manager = Manager(app)
    
    app.config.from_object('settings.TestingConfig')
    
    @app.route('/')
    def hello_world():
        return "index"
    
    
    @manager.command
    def func(args):
        """
        自定义命令
        python manage.py[文件名] custom[函数名] 123[参数]
        """
        print("执行func",args) #执行func 123
    
    
    
    @manager.option("-n","--name",dest='name')
    @manager.option("-u","--url",dest='url')
    def foo(name,url):
        """
        关键字传参
        python 文件名 函数名 -n[--name]参数 -u[--url]参数
        """
        print(name,url)
    
    
    if __name__ == '__main__':
        # 命令行启动项目:python manage.py[文件名] runserver
        manager.run()
    

    Flask-migrate

    安装

    pip install flask-migrate

    使用

    from flask import Flask
    from flask_script import Manager
    from flask_sqlalchemy import SQLAlchemy
    from flask_migrate import Migrate,MigrateCommand
    
    db = SQLAlchemy()
    
    app = Flask(__name__)
    
    app.config.from_object("settings.DevelopmentConfig")
    
    manager = Manager(app)
    
    # 将db注册到app中
    db.init_app(app)
    
    
    migrate = Migrate(app,db)
    
    manager.add_command('db', MigrateCommand)
    """
    # 数据库迁移命名
        python manage.py db init
        python manage.py db migrate
        python manage.py db upgrade
    """
    
    @app.route('/')
    def hello_world():
        return "index"
    
    
    @manager.command
    def func(args):
        """
        自定义命令
        python manage.py[文件名] custom[函数名] 123[参数]
        """
        print("执行func",args) #执行func 123
    
    
    
    @manager.option("-n","--name",dest='name')
    @manager.option("-u","--url",dest='url')
    def foo(name,url):
        """
        关键字传参
        python 文件名 函数名 -n[--name]参数 -u[--url]参数
        """
        print(name,url)
    
    
    if __name__ == '__main__':
        # 命令行启动项目:python manage.py[文件名] runserver
        manager.run()
    manage.py
    class BaseConfig(object):
        # SESSION_TYPE = 'redis'  # session类型为redis
        # SESSION_KEY_PREFIX = 'session:'  # 保存到session中的值的前缀
        # SESSION_PERMANENT = True  # 如果设置为False,则关闭浏览器session就失效。
        # SESSION_USE_SIGNER = False  # 是否对发送到浏览器上 session:cookie值进行加密
    
        SQLALCHEMY_DATABASE_URI = "mysql+pymysql://root:@0.0.0.0:3306/day146?charset=utf8"
        SQLALCHEMY_POOL_SIZE = 5
        SQLALCHEMY_POOL_TIMEOUT = 30
        SQLALCHEMY_POOL_RECYCLE = -1
    
        # 追踪对象的修改并且发送信号
        SQLALCHEMY_TRACK_MODIFICATIONS = False
    settings.py
    from script import db
    
    
    
    class Users(db.Model):
        """
        用户表
        """
        __tablename__ = 'users'
        id = db.Column(db.Integer, primary_key=True)
        username = db.Column(db.String(80), unique=True, nullable=False)
        # email = db.Column(db.String(120), unique=True, nullable=False)
    
        def __repr__(self):
            return '<User %r>' % self.username
    model.py

      

  • 相关阅读:
    mySQL 重点
    JS代码预解析原理、函数相关、面向对象
    PHP中对数组进行操作的常用函数总结
    js函数和数组总结
    深入理解css网页布局细节
    AngularJS表单验证
    发送消息 缺少 更新的字段值
    springboot 下 logback + MDC的使用
    Mock的使用2
    StringUtils # split 的坑
  • 原文地址:https://www.cnblogs.com/zhoujunhao/p/8611059.html
Copyright © 2011-2022 走看看