Flask 自建扩展

Python微信订餐小程序课程视频

https://edu.csdn.net/course/detail/36074

Python实战量化交易理财系统

https://edu.csdn.net/course/detail/35475

  • 自建扩展介绍

    • Flask扩展分两类
      1. 纯功能, 如: Flask-Login 提供用户认证
      2. 对已有的库和工具包装(简化继承操作,并提供有用的功能,更方便)
        如: Flask-SQLAlchemy 包装了 SQLAlchemy
    • 涉及的 python 包
      1. setuptools
      2. wheel
      3. twine: 发布python 包 (发布到 PyPI 后才能使用 pippipenv 安装)
      4. readme_renderer: 将 mdrsttxt 文本 渲染成.html
    • 命名:
      1. 扩展的名称: Flask-<功能/第三方库名> 或 <功能/第三方库名>-Flask
      2. 扩展的包名: flask_<功能/第三方库名> (小写加下划线)
  • 扩展类实现

    • 编写扩展类(以 Flask-Share 为例)
      • 使用扩展步骤: 导入扩展类 - 实例化 - 传入 app 初始化
      from flask_share import Share
      share = Share()  # extensions.py 中统一实例化所有扩展
      share.init_app(app) # 在工厂函数中统一初始化所有扩展
      # 也可以一步到位
      # share = share(app) 
      
      
      • 新建扩展类 (flask_share/__init__.py)
      class Share(object):
        def \_\_inti\_\_(self, app=None):
          self.init_app(app)
          
        def init\_app(self, app):
          # 兼容 0.7 以前版本
          if not hasattr(app, 'extensions'): 
            app.extensions={}
            
          # 在 app 应用中存储所有扩展实例, 可验证扩展是否完成实例化
          app.extensions['share'] = self
          
          # 扩展类添加到模板上下文中
          app.jinja_env.globals['share'] = self
          # app.context\_processor(lambda:{'share': self})
          
          # 扩展配置, 初始化后添加到 app.config 中, 以 SHARE\_ 开头避免冲突
          app.config.setdefault('SHARE\_SITES', 'weibo,wechat,douban,facebook,twitter,google,linkedin,qq,qzone')
          app.config.setdefault('SHARE\_MOBILESITES','weibo,douban,qq,qzone')
          app.config.setdefault('SHARE\_HIDE\_ON\_MOBILE', False)
          app.config.setdefault('SHARE\_SERVER\_LOCAL', False) # 是否使用内置资源
      
      
    • 实现扩展功能
      • 加载静态资源
      class Share(object):
       @staticmethod
        def load(css\_url=None, js\_url=None):
          
          if current_app.config('SHARE\_SERVE\_LOCAL'):# 使用本地进入条件
            css_url = url_for('share.static', filename='css/share.min.css')
            js_url = url_for('share.static', filename='js/share.min.js')
          
          if css_url is None:
            css_url = 'https://cdn.bootcss.com/social.share.js/1.0.16/css/share.min.css'
          if js_url is None:
            js_url = 'https://cdn.bootcss.com/social-share.js/1.0.16/js/social-share.min.js'
          return Markup('''\n
       '''% (css_url, js_url))
        
        def init\_app(self, app):
          # app.static\_url\_path 的引用是为了和用户设置一致
          blueprint = Blueprint('share', __name__, static_folder='static',
                               static_url_path='/share'+ app.static_url_path)
          app.register_blueprint(blueprint)
          
          
        
      
      
      • 创建前端分享组件
      class Share(object):
       @staticmethod
        def create( title='', sites=None, mobile\_sites=None,align='left',addtion\_class=''):
          if sites is None:
            sites = current_app.config['SHARE\_SITES']
          if mobile_sites is None:
            mobile_sites = current_app.config['SHARE\_MOBILE\_SITES']
            
          return Markup('''
       
       %s'''%(addition_class, sites, mobile_sites,align, title ))
          
      
      
      • 在模板中使用
      {{ share.create('分享到:') }}
      
      
  • 开源发布准备

      1. 添加文档字符串与注释后的完整代码
    """
     Flask-Share 
     # ~~~~~~~~~~~~~~ 
     Create social share component in Jinja2 tempalte based on share.js. 
     :copyright: (c) 2017 by Gavin Li. 
     :license: MIT, see LICENSE for more details. 
    """
    
    import re 
    from flask import current_app, url_for, Markup, Blueprint, request
    
    class Share(object):
        
     @staticmethod
      def load(css\_url=None, js\_url=None):
        """ Load share.js resourse.
     
     :param css\_url: if set, will be used as css url
     :param js\_url: if set, will be used as js url
     :param serve\_local: if set to True, the local resource will be used
     """
      
     @staticmethod
      def create( title='', sites=None, mobile\_sites=None,align='left',addtion\_class=''):
        """ Create a share component.
     
     :param title: the prompt displayed on the left of the share component.
     :param sites: a string that consist of sites, separate by comma.
     :param mobile\_sites: a string that consist of sites, separate by comma.
     supported site name: weibo, wechat, douban, facebook, twitter, google, linkedin, qq, qzone."
     for example: weibo,wechat, qq.
     :param mobile\_sites: the sites displayed on mobile.
     :param align: the align of the share component,default to '`left`'.
     :param addition\_class: the style class added to the share component.
     """
       
    
    
      1. 编写 README 与文档
      • 小项目 直接用 README概括所有的必需的说明
      • 大项目 比较复杂的,多文件组织文档内容
        将项目部署到 Read the Docs上
        Sphinx + Github + Readthedocs的工作流编写和部署文档
      1. 定义 python 包的元数据:(setup.py)
    """
     Flask-Share
     
     Create social share component in Jinja2 template based on share.js.
     :copyright: (c) 2022 by Gavin li.
     :license: MIT, see LICENSE for more details.
    """
    form os import path
    from codecs import open
    form setuptools import setup
    
    basedir = path.abspath(path.dirname(__file__))
    
    # Get the long description from the README file
    with open(path.join(basedir,'README.md'), encoding='utf-8') as f:
      long_description = f.read()
      
    setup(
      name='Flask-Share', # 包名称
      version='0.1.0',  # 版本
      url='https://github.com/lghpython/flask-share',
      license='MIT', 
      author='xxx'
      author_email='[email protected]',
      description='xxx',
      long_description=long_description,
      long_description_content_type='text/markdown', # 默认渲染格式为 rst
      platforms='any',
      packages=['flask\_share'], # 包含的包列表,包括子包,可用find\_pakages()
      zip_safe=False,
      test_suite='test\_flask\_share', 测试包或模块
      include_package_data=True, 
      install_requires=['Flask'],  # 安装依赖
      keywords='flask extension development', # 项目关键词
      classifiers=[ # 分类词, 在 PyPI 中设置分类
        'DevelopmentStatus::3-Alpha',
        'Environment::WebEnvironment',
        'IntendedAudience::Developers',
        'License::OSIApproved::MITLicense',
        'ProgrammingLanguage::Python',
        'ProgrammingLanguage::Python::2',
        'ProgrammingLanguage::Python::2.7',
        'ProgrammingLanguage::Python::3',
        'ProgrammingLanguage::Python::3.3',
        'ProgrammingLanguage::Python::3.4',
        'ProgrammingLanguage::Python::3.5',
        'ProgrammingLanguage::Python::3.6',
        'Topic::Internet::WWW/HTTP::DynamicContent',
        'Topic::SoftwareDevelopment::Libraries::PythonModules']
      ],
    )
    
    
      1. 指定打包其他文件: MANIFEST.in
        需要在 setup()方法中设置: include_package_data=True
    graft flask_share/static
    include LICENSE test_flask_share.py
    # exclude 用来排除匹配文件
    # recursive-include 递归匹配
    # recursive-exclude 递归排除匹配
    # graft 目录 包含目录下所有
    # prune 目录 配出目录下所有
    
    
      1. 编写单元测试
    import unittest
    
    from flask import Flask, render_template_string, current_app
    from flask_share import Share
    
    class ShareTestCase(unittest.TestCase):
      
      def setUp(self):
        self.mobile_agent={{'HTTP\_USER\_AGENT':'Mozilla/5.0(iPhone;CPUiPhoneOS9\_1likeMacOSX)\
     AppleWebKit/601.1.46(KHTML,likeGecko)Version/9.0Mobile/13B143Safari/601.1'}}
    	app = Flask(__name__)
        app.testing=True
        self.share=Share(app)
        
     @app.route('/')
        def index():
          return render_template_string('{{share.load() }}\n {{share.create() }}')
        # 推送上下文
        self.context=app.app_context()
        self.context.push()
        self.client - app.test_client()
        
      def tearDown(self):
        self.context.pop()
        
      def test\_create\_on\_mobile(self):
        current_app.config['SHARE\_HIDE\_ON\_MOBILE'] = True
        response = self.client.get('/', environ_base=self.mobile_agent)
        data = response.get_data(as_text=True)
        self.assertIn('social-share.min.js', data)
        self.assertNotIn(', data))
     
    
    
      1. setup.cfg
  • 发布到 PyPI

    • 创建 PyPI 账号
      • 注册访问
      • 方便访问: 创建 .pypirc文件, 放置$HOME/.pypirc(win) 或~/.pypir(mac linux) 明文密码限制访问权限
      [distutils]
      index-servers=
      	pypi
          
      [pypi]
      username: 用户名
      password: 密码
      
      
    • setuptools 打包
      • 创建 Source Distributions 包
      python setup.py sdist
      
      
      • 创建 Wheel 包
      python setup.py bdist_wheel
      
      
      • 合并命令
      python setup.py sdist bdist_wheel
      
      
    • twine 上传
      • 安装 twine
      pipenv install twine --dev
      
      
      • 上传
      twine upload dist/*
      
      
  • 编写良好的扩展

    • 命名规范(Flask-Foo 或 Foo-Flask)
    • 使用相对宽松的开源许可证(MIT/BSD)
    • 支持工厂模式(添加 initi_app() 方法)
    • 支持同时运行多程序实例( 使用 current_app 获取程序实例)
    • 包含 setup.py脚本,并列出所有安装依赖(必需)
    • 包含单元测试
    • 编写文档并在线发布
    • 上传到 PyPI

你可能感兴趣的:(it,安全,计算机,服务器)