一、什么是Blueprints
blueprint定义了可应用于应用程序的视图、模板、静态文件和其他元素的集合。例如,假设我们有一个管理面板的蓝图。这个蓝图将为诸如/admin/login和/admin/dashboard之类的路由定义视图。它还可能包括服务这些路由所需提供的模板和静态文件。然后我们可以使用这个蓝图为我们的应用添加一个管理面板,无论是宇航员的社交网络还是火箭销售员的CRM。
二、你为什么要用蓝图?
蓝图的关键用例是将我们的应用程序组织成不同的组件。对于类似twitter的微博,我们可以为网站页面制定蓝图,比如index.html和about.html。然后我们可以有另一个用于登录的仪表板,我们在其中显示所有最新的文章,还有一个用于管理员面板。站点的每个不同区域也可以被划分为代码的不同区域。这让我们把我们的应用程序设计成几个更小的“应用程序”,每个应用程序都只做一件事。
三、你把它们放在哪里?
就像所有的Flask一样,我们可以用很多方法来组织我们的应用程序。如果采用了蓝图,我们就可以考虑将其作为functional与divisional 的选择(从商业世界中借用的术语)。
3.1功能结构
有了功能结构,你就可以通过他们(蓝图)的工作来组织你的应用程序。模板被分组在一个目录中,静态文件在另一个目录中,视图在第三个目录中。
除了您的app/view /__init__.py之外,这个清单中的yourapp/views/目录中的每个.py文件都是蓝图。在您的app/__init__.py中,我们将导入这些蓝图并将它们注册到Flask()对象上。我们将在本章后面进一步了解如何实现这一点。
3.2分区结构
通过分区结构,您可以根据应用程序的哪个部分来组织应用程序的各个部分。管理面板的所有模板、视图和静态文件都放在一个目录中,而用户控制面板的所有模板都位于另一个目录中。
使用这个清单中的 分区结构,您的yourapp/下的每个目录都是一个单独的蓝图。所有的蓝图都被应用到顶级__init__.py中的Flask()应用程序。
4、哪一个是最好的?
你选择的组织结构很大程度上是一个个人决定。唯一的区别是层次结构的表示方式——即您可以使用任何一种方法来构建Flask应用程序——因此您应该选择对您有意义的那个。
如果你的应用程序有很多独立的部分,它们只共享模型和配置等内容,那么分区可能是最好的选择。一个例子可能是一个SaaS应用,它可以让用户建立网站。您可以在“分区”中为主页、控制面板、用户网站和管理面板提供蓝图。这些组件可能有完全不同的静态文件和布局。如果您正在考虑将蓝图作为扩展或将其用于其他项目,那么分区结构将更容易使用。
另一方面,如果你的应用程序的组件更多地结合在一起,它可能会更好地用功能结构来表示。Facebook就是一个例子。如果Facebook使用Flask,它可能会有静态页面的蓝图(比如注册home、register、about等)、仪表板(比如新闻提要)、个人资料(/robert/about和/robert/photos)、设置(/settings/security和/settings/privacy)等等。这些组件都有一个总体布局和样式,但是每个组件都有自己的布局。下面的清单显示了一个非常精简的版本,如果用Flask构建的话,Facebook可能看起来像它。
facebook/view /视图中的蓝图只不过是视图的集合,而不是完全独立的组件。相同的静态文件将用于大多数蓝图中的视图。大多数模板将扩展一个主模板。功能结构是组织这个项目的好方法。
5、你如何使用它们?
5.1基本用法
让我们看一下Facebook示例的一个蓝图的代码。
要创建blueprint对象,我们导入blueprint()类,并使用参数名和import_name初始化它。通常import_name只是__name__,它是一个特殊的Python变量,包含当前模块的名称。
我们在这个Facebook的例子中使用了一个功能结构。如果我们使用的是分区结构,我们希望告诉Flask蓝图有自己的模板和静态目录。这个代码块显示了它的样子。
我们现在已经定义了蓝图。是时候在Flask应用上注册了。
现在,在facebook/views/profile.py(例如/)中定义的路由在应用程序上注册,就像您用@app.route()定义它们一样。
5.2使用动态URL前缀。
继续Facebook示例,请注意所有的配置文件路由如何从user_url_slug部分开始,并将该值传递给视图。我们希望用户能够访问一个URL,比如https://facebo-ok.com/john.doe。我们可以通过为所有blueprint的路由定义一个动态前缀来停止重复自己。
蓝图让我们定义静态和动态前缀。我们可以告诉Flask,蓝图中的所有路线都应该以/profile为前缀;这是一个静态的前缀。在Facebook的例子中,前缀会根据用户浏览的资料而改变。无论他们选择什么文本,都是我们应该显示的资料文件的URL段;这是一个动态前缀。
在定义前缀时,我们有一个选择。我们可以在以下两种情况之一中定义前缀:实例化Blueprint()类时或使用app.register_blueprint()注册时。
虽然这两种方法都没有任何技术上的限制,但是最好将前缀放在与注册相同的文件中。这使得从顶层移动东西更容易。出于这个原因,我建议在注册时设置url_prefix。
我们可以使用转换器使前缀成为动态的,就像route()调用一样。这包括我们定义的任何自定义转换器。使用转换器时,我们可以在将给定的值传递给视图之前对其进行预处理。在本例中,我们希望基于传入到配置文件蓝图的URL slug获取用户对象。我们将使用url_value_preprocessor()来修饰函数。
我们使用g对象来存储profile文件所有者,并且在Jinja2模板上下文中可以使用g。这意味着对于一个基本的情况,我们在视图中所要做的就是呈现模板。我们需要的信息将在模板中提供。
5.3使用动态子域名
如今,许多SaaS(软件即服务)应用程序为用户提供了访问软件的子域。例如,Harvest是一个咨询顾问的时间跟踪应用程序,它允许您从yourname.harvestapp.com访问您的仪表板。在这里,我将向您展示如何使Flask使用自动生成的子域。
对于本节,我将使用一个应用程序示例,该应用程序允许用户创建自己的网站。想象一下,我们的应用有三个不同部分的蓝图:用户注册的主页,用户创建网站的用户管理面板和用户的网站。由于这三个部分是相对不相连的,我们将按分区结构组织它们。
这张表解释了这款应用中不同的蓝图。
我们可以像定义URL前缀一样定义动态子域。这两个选项都是可用的,但是我们将在sitemaker/__init.py__中保留这些定义。
由于我们使用的是分区结构,我们将在sitemaker/site/__init__.py中定义蓝图。
现在,我们从数据库中获得了站点信息,我们将使用它将用户的站点显示给请求子域名的访问者。
要使Flask与子域一起工作,我们需要指定SERVER_NAME配置变量。
6、重构小应用程序以使用蓝图
我想简单介绍一下如何将应用程序转换成蓝图。我们将从一个典型的Flask应用程序开始,并对其进行重组。
views.py文件已经增长到10,000行代码!我们一直在推迟重构,但现在是时候了。该文件包含站点的每个部分的视图。这些部分是主页、用户仪表板、管理仪表板、API和公司博客。
第一步:Divisional还是functional?
这个应用程序由非常不同的部分组成。例如,模板和静态文件可能不会在用户仪表板和公司博客之间共享。我们将采用Divisional。
步骤2:移动一些文件
接下来,我们将为我们的新应用程序创建目录树。然后,我们将views.py、static/和templates/全部复制到每个blueprint目录。然后,我们可以从顶级包目录中删除它们。
第三步:少废话
现在,我们可以进入每个蓝图并删除不适用于该蓝图的视图、静态文件和模板。你如何完成这一步很大程度上取决于你的应用一开始是如何组织的。
最终的结果应该是每个蓝图都有一个viewspy文件,其中包含该蓝图的所有视图。没有两个蓝图应该为相同的路线定义一个视图。每个templates/目录只应该包含该蓝图中视图的模板。每个static/目录应该只包含应该由该蓝图公开的静态文件。
步骤4:Blueprint...ifi...cation or something
这是我们将目录转换成蓝图的部分。关键是在__init__py文件中。首先,让我们看一下API蓝图的定义。
接下来,我们可以在U2FtIEJsYWNr包的顶级__init___.py文件中注册这个蓝图。
确保这些路由现在已经在设计图上注册,而不是应用程序对象。
第五步:享受
现在我们的应用程序比以前的一个大型viewspy文件模块化得多。路由定义更简单,因为我们可以将它们分组到蓝图中,并为每个蓝图配置子域和URL前缀。
7、总结
blueprint是视图、模板、静态文件和其他可应用于应用程序的扩展的集合。
蓝图是组织应用程序的好方法。
在分区结构中,每个蓝图都是视图、模板和静态文件的集合,它们构成了应用程序的特定部分。
在功能结构中,每个蓝图只是视图的集合。模板和静态文件都保存在一起。
要使用蓝图,您需要定义它,然后通过调用Flask.register_blueprint()在应用程序上注册它。
您可以定义一个动态URL前缀,该前缀将应用于蓝图中的所有路由。
您还可以为蓝图中的所有路由定义一个动态子域。
重构一个不断增长的应用程序来使用蓝图可以在五个相对小的步骤中完成。
https://segmentfault.com/a/1190000002480266