实验5、Flask设计模式和Web服务体验
1. 实验内容
Flask appbuilder包括基本的表单验证,内置管理模块。本节主要学习Flask appbuilder的后台管理模块使用和对Flask设计模式拓展作简要介绍
2. 实验要点
- 掌握安装和配置Flask环境
- 尝试编写Flask版"Hello World"
3.实验环境
- Centos 7.9
4. 工作目录
本实验的工作目录为: /experiment
Flask 设计模式
Flusk
Flusk是一个可用于创建包括SQLAlchemy,Docker和Nginx的大型Flask应用程序的例子。它具有漂亮的逻辑分离,可将后端,域,视图和模型创建到各自的层中。
它很好地使用了Flask蓝图,并遵循Factory设计模式。在Flusk中创建扩展很容易,并且使用Docker可以更轻松地将应用程序容器化。在这里查看其源代码。
Cookiecutter Flask
Cookiecutter Flask是一个烧瓶模板,具有诸如资产捆绑和Webpack压缩之类的功能。它具有用于用户注册/身份验证的入门模板,并基于Bootstrap 4构建。
Cookiecutter是创建Python软件包项目的命令行实用程序。这意味着,如果您使用此模板,则也可以将Flask应用程序发布为PyPI。该项目正在积极开发中,在此链接。
Flask Full
Flask full是又一个功能强大的样板,它利用了Celery,MongoEngine,Signals,Shell命令,WebSocket和eventlet。它与Swagger API文档和Sphinx文档很好地集成在一起,它可以从这里下载。
Flasky
对于创建轻量级应用程序,您可能需要考虑Flasky。Flasky的源代码可在此处获得。该存储库是由Miguel Grinberg创建的,他在Web开发方面拥有超过25年的经验。
他创建了Flasky来为他的名为Flask Web Development的书中讨论的概念提供代码示例。
无论选择哪种框架或模板,所有这些都具有一些标准功能,并以各自的方式进行讨论。我们在这里列出其中一些功能并进行讨论,并在本系列教程的示例应用程序中使用Flask-Appbuilder来实现这些功能。
本教程讨论了一些更常见的模式,您可以在当今几乎所有的Web应用程序中找到这些模式,并且很高兴将其包含在Web开发人员的工具包中。
Flask登录示例
离线创建用户
启动MongoDB服务
mongod --dbpath /var/lib/mongodb --logpath /var/log/mongodb/mongod.log --fork
让我们通过使用flask fab create-user
命令创建一个用户。使用此命令后,您将获得命令行提示以提供用户帐户的详细信息。提供类似于以下所示的详细信息,即可创建您的用户。
请注意,在命令输出的末尾,sqla.manager打印确认消息以供用户创建。
现在访问该应用程序,并使用您刚才输入的详细信息登录。如果您在生产数据库上创建了用户,则将这些详细信息传递给您为其创建此帐户的人。
导航到IP:8080/login
,您将看到如下所示的登录表单。
一旦user1登录,用户即可看到欢迎消息。
Flask admin
如果您阅读了该Flask教程系列中的其他教程,那么您会发现我们已经利用了Flask-Appbuilder附带的内置安全性。我们使用add_view_no_menu添加的视图不受保护。但是,我们基于DataModels添加的视图将自动受到Admin用户的保护。
另外,我们可以使用Flask-Admin,它通常会达到类似的结果。也是Flask-Admin,让我们以面向对象的方式定义视图。前端上的网页表示我们明确添加到界面的视图类上的方法。
在本教程中,我们不使用Flask-Admin。取而代之的是,我们采取了更快地获得相同结果的途径,并跳过了了解有关登录,身份验证,角色和权限的安全性的必要性。当我们使用Flask-Appbuilder时,这是可能的。
Flask-Appbuilder和Flask-Admin都有其优缺点。对于Flask-Admin,我们必须知道没有现有的安全性假设,并且您可以基于安全性模型创建应用程序。要了解有关Flask-Admin的更多信息,请访问此处 并查看适当的示例。
Flask文件上传
近来几乎所有的Web应用程序都具有存储和提供文件的要求。它们的典型模式是将文件保存在服务器上的某个路径上,并提供一些信息以对存储的文件进行操作并保存在应用程序模型和视图中。
我们将研究一个类似的例子。让我们用其他功能修改我们的Song模型。
修改models.py
文件
from flask import Markup, url_for
from flask_appbuilder.models.mixins import FileColumn
from flask_appbuilder.filemanager import get_file_original_name
from flask_appbuilder import Model
from sqlalchemy import Column, Integer, String, ForeignKey
from sqlalchemy.orm import relationship
class Song(Model):
id = Column(Integer, primary_key=True)
title = Column(String(200), nullable=False)
rating = Column(Integer)
album_id = Column(Integer, ForeignKey('album.id'))
song_file = Column(FileColumn, nullable=False)
album = relationship("Album")
def __str__(self):
return self.title
def download(self):
return Markup(
'<a href="' +
url_for("SongsView.download", filename=str(self.song_file)) +
'">Download</a>'
)
def file_name(self):
return get_file_original_name(str(self.song_file))
我们通过添加类型为FileColumn的新列来修改了先前创建的Song模型。此外,我们添加了另外两列,这些列将添加到SongsView中以显示“文件名”和一个链接,以下载上载的文件。
Flask url_for方法已与标记一起使用,以将下载显示为链接。同样,我们使用了Flask-Appbuilder中的get_file_original_name方法,因为通过将文件名与UUID串联在一起来存储文件名,以避免相同文件名之间的冲突。
修改views.py
class SongsView(ModelView):
datamodel = SQLAInterface(Song)
label_columns = {"file_name" : "File Name", "download": "Download"}
list_columns = ["title", "file_name", "download"]
show_columns = ["title", "file_name", "download"]
在SongsView类中,我们提到了需要显示的新标签,并且我们只想列出指定列表中提到的列。
在这里您需要记住,我们已经通过在模型中添加一列来修改数据库模型。数据库中的对应表没有此新列。因此,从上一教程开始,我们就在处理SQLite数据库时,将删除app.db文件。
或者,我们也可以使用flask db migration
命令对版本文件进行必要的更改,然后使用flask db upgrade
更新表。但是,我们引入的更改很小,我们可以重新创建应用程序数据库和用户。
我们建议在生产中,只要对应用程序的数据库架构进行任何更改,都应考虑使用Flask-Migrate命令。
使用以下命令删除数据库文件并创建用户
rm app.db
flask fab create-db
flask fab create-admin
现在,使用管理员凭据登录到应用程序,您将看到修改后的SongsView,如下图所示。
请注意config.py
中的以下值。上载的文件将存储在服务器上的该路径上。对于本教程,它将被上载到我们正在开发此示例应用程序的机器上。
检查上传路径,如config.py中所述。文件与UUID一起存储,如下所示。
Flask HTTPS
就开发而言,我们可能会继续运行不使用HTTPS的Flask应用程序。从安全角度来看,HTTPS确保合法客户端和服务器之间进行通信。
这种加密的通信要求使用带有一对公钥和私钥的CA签名证书在客户端和服务器之间建立信任。请在这里阅读更多
在本教程中,我们将让您知道在开发过程中使用HTTP开发基于Flask的网站的方法。
在开发过程中包括HTTPS的最快和最简单的方法是使用adhoc ssl_context
,如下面在run.py
中所述。但是,请在环境中使用pip安装pyopenssl。
app.run(host ='0.0.0.0',port = 8080,debug = True,ssl_context ='adhoc')
添加ssl_context后,当您导航到https://IP:8080
时,将收到警告,怀疑对此通信中使用的证书的有效性。此外,导航到http://IP:8080
将不再起作用。
因此,这种方法有点麻烦,并且要求您在重新启动开发服务器时始终接受此请求。
另外,要使用https功能进行开发,我们可以将路径传递到证书,然后将Python Tuple中的密钥输入到run方法中的ssl_context参数。但是,要采用这种方法,您将必须使用以下命令生成自签名证书和密钥。
openssl req -x509 -newkey rsa:4096 -nodes -out mycert.pem -keyout mykey.pem -days 365
我们使用了所有默认值。现在停止开发服务器,并通过路径证书和密钥路径,如下所示。
app.run(host ='0.0.0.0',port = 8080,debug = True,ssl_context =('mycert.pem','mykey.pem'))
此方法也类似于以前使用Adhoc ssl_context的方法。但是,在这种情况下,细节将保留更长的时间。我们提到了365天。您可以指定所需的到期日。此外,如果您在团队中进行开发,则可以与其他团队成员共享这些文件。
在生产环境中,证书由CA颁发,Miguel Grinberg在此处讨论一些用例。我们建议您在该页面上阅读更多详细信息。
实验总结
在本教程中,我们讨论了Web开发人员在开发与Flask登录,Flask管理,Flask文件上传和Flask HTTPS相关的功能时遵循的一些模式。我们提供了代码示例,读者也可以尝试。
在我们的下一个教程中,我们将介绍扩展Flask的概念,并了解如何创建基于REST API的功能。此外,我们将讨论如何在Flask中使用Twitter API。