-
自建扩展介绍
- Flask扩展分两类
- 纯功能, 如: Flask-Login 提供用户认证
- 对已有的库和工具包装(简化继承操作,并提供有用的功能,更方便)
如: Flask-SQLAlchemy 包装了 SQLAlchemy
- 涉及的 python 包
setuptools
:wheel
:twine
: 发布python
包 (发布到PyPI
后才能使用pip
或pipenv
安装)readme_renderer
: 将md
、rst
、txt
文本 渲染成.html
- 命名:
- 扩展的名称: Flask-<功能/第三方库名> 或 <功能/第三方库名>-Flask
- 扩展的包名: flask_<功能/第三方库名> (小写加下划线)
- 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) # 是否使用内置资源
- 使用扩展步骤: 导入扩展类 - 实例化 - 传入 app 初始化
- 实现扩展功能
- 加载静态资源
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(\'\'\'<link rel=\"stylesheet\" href=\"%s\">\\n <script src=\"%s\"></script>\'\'\'% (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(\'\'\' <div class=\"social-share %s\" data-sites=\"%s\" data-mobile-site=\"%s\"align=\"%s\"> %s</div>\'\'\'%(addition_class, sites, mobile_sites,align, title ))
- 在模板中使用
{{ share.create(\'分享到:\') }}
- 加载静态资源
- 编写扩展类(以 Flask-Share 为例)
-
开源发布准备
-
- 添加文档字符串与注释后的完整代码
\"\"\" 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. \"\"\"
-
- 编写 README 与文档
- 小项目 直接用 README概括所有的必需的说明
- 大项目 比较复杂的,多文件组织文档内容
将项目部署到 Read the Docs上
Sphinx + Github + Readthedocs的工作流编写和部署文档
-
- 定义 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=\'xx@xx.com\', 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\'] ], )
- 定义 python 包的元数据:(
-
- 指定打包其他文件: MANIFEST.in
需要在 setup()方法中设置: include_package_data=True
graft flask_share/static include LICENSE test_flask_share.py # exclude 用来排除匹配文件 # recursive-include 递归匹配 # recursive-exclude 递归排除匹配 # graft 目录 包含目录下所有 # prune 目录 配出目录下所有
- 指定打包其他文件: MANIFEST.in
-
- 编写单元测试
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(\'<div class=\"socail-share\"\', data))
-
- 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
- 创建 Source Distributions 包
- twine 上传
- 安装 twine
pipenv install twine --dev
- 上传
twine upload dist/*
- 安装 twine
- 创建 PyPI 账号
-
编写良好的扩展
- 命名规范(Flask-Foo 或 Foo-Flask)
- 使用相对宽松的开源许可证(MIT/BSD)
- 支持工厂模式(添加 initi_app() 方法)
- 支持同时运行多程序实例( 使用 current_app 获取程序实例)
- 包含 setup.py脚本,并列出所有安装依赖(必需)
- 包含单元测试
- 编写文档并在线发布
- 上传到 PyPI
来源:https://www.cnblogs.com/lghgo/p/15978176.html
本站部分图文来源于网络,如有侵权请联系删除。