大多数Python框架通常分为两类,一类是像Flask和FastAPI这样的简约型框架,另一类是包含电池的更强大的框架,如流行的Django框架。
然而,Django有一个相当陡峭的学习曲线,主要是因为它的模式与几乎所有其他的Python框架都非常不同。例如,其他框架所称的控制器动作在Python中被称为视图。
Django项目被组织成应用程序,这有时会混淆典型的MVC组织,但却提供了模块化的好处。如果不使用像DjangoRestFramework这样的库,建立一个Rest API是相当复杂的。Django的文件夹结构经常导致多个文件夹和子文件夹的名称相同,造成团队之间的混乱。
虽然许多开发者仍然在使用并喜爱Django,但人们公认需要一个遵循更多传统框架模式的框架,类似于Ruby的Rails、PHP的Laravel或NestJS所使用的框架。Masonite框架允许我们使用Python与一个更强大、更熟悉的框架。
在本教程中,我们将通过建立一个简单的待办事项列表来熟悉Masonite。要跟上本教程,你需要安装Python ≥v3.6。首先,让我们回顾一下Masonite的一些特性和好处。
Masonite的特点
- 开箱即用的电子邮件支持
MailProvider,SMTP, 和MailgunDriver - IOC容器和自动解决的依赖性注入
- 服务提供商可以很容易地在框架中添加功能
- 极其简单的静态文件配置
- Masonite ORM。类似于Active Record的Orator的落地式替代品
- 包括一个有用的命令行工具,称为craft 命令
- 使用
BroadcastProvider、pusher、ably和pubnub驱动程序从你的服务器发送WebSocket请求 - 极具可扩展性
创建一个新的Masonite项目
首先,让我们创建一个新的虚拟环境。
python -m venv venv
要激活你的虚拟环境,运行source ./venv/bin/activate 。要停用,使用命令deactivate 。接下来,按以下方式安装Masonite。
pip install masonite
用下面的命令创建一个新的项目。
craft new firstproject
接下来,导航到firstproject 目录。运行下面的代码来安装额外的依赖项。
craft install
实质上,craft 是一个命令,在Masonite中工作时充当前缀,类似于Rails和Laravel中的rails 和artisan 命令。
Masonite术语
Masonite的术语与Rails、Laravel和其他大多数MVC Web框架的术语都很相似。
- 控制器。包含若干方法的类,称为动作
- 行动。控制器的方法,决定如何响应特定的请求
- 路由。确定哪些URL或方法组合应该被引导到哪些控制器动作的规则
Masonite控制器
现在,我们将创建我们的第一个控制器。
craft controller First
上面的命令将创建app/http/FirstController.py 文件,其中包含以下代码。
"""A FirstController Module."""
from masonite.request import Request
from masonite.view import View
from masonite.controllers import Controller
class FirstController(Controller):
"""FirstController Controller Class."""
def __init__(self, request: Request):
"""FirstController Initializer
Arguments:
request {masonite.request.Request} -- The Masonite Request class.
"""
self.request = request
def show(self, view: View):
pass
在__init__ 函数定义中,我们声明了一个名为request 的参数。request 使用依赖注入,使请求对象(包含URL参数、查询等)对我们所有的路由可用。另外,你可以在一个动作的基础上声明参数,比如show 方法上的view 参数。
渲染模板和视图
假设你正在构建一个全栈应用程序,它将渲染一个模板;我们将使用我们传入show 方法的view 参数,渲染所需的模板。
def show(self, view: View):
return view.render("helloworld", {"phrase": "Hello World"})
上面的代码告诉Masonite在/resources/templates 中寻找一个叫做helloworld.html 的模板,并使用作为第二个参数传递的字典中的数据渲染它。
要创建附带的view ,运行命令craft view helloworld 。最后,在新创建的resources/templates/helloworld.html 中加入下面的代码。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Hello World</title>
</head>
<body>
<h1>{{ phrase }}</h1>
</body>
</html>
创建Masonite路由
要看到上面的代码在工作,我们只需要将控制器连接到一个路由,这样它就可以渲染view 。打开routes/web.py ,让我们添加我们的路由,如下所示。
"""Web Routes."""
from masonite.routes import Get, Post
ROUTES = [
Get("/", "WelcomeController@show").name("welcome"),
Get("/first", "FirstController@show").name("first")
]
我们使用Get 函数来声明一个GET 请求的路由。第一个字符串表示路由的URL,第二个字符串表示控制器中应该被调用的动作。在我们的例子中,我们从FirstController 中调用show 。name 方法允许我们给我们的路由一个名字,我们将用它来引用我们模板中的链接。
现在,你可以用命令craft serve 来运行服务器。我们可以看到我们的页面在localhost:8000/first 。这是很容易的!
发送JSON数据
发送JSON数据是非常简单的。我们将在我们的动作中返回一个字典或一个数组。如果我们在FirstController 中对我们的show 动作进行如下修改,当你在浏览器中检查该页面时,迎接你的将是JSON数据。
def show(self, view: View):
return {"Hello": "World"}
迁移的工作
为了给我们的应用程序设置迁移,首先,我们要在.env 文件中配置数据库的详细信息。
DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=masonite
DB_USERNAME=root
DB_PASSWORD=root
DB_LOG=True
DB_CONNECTION 字段对应于config/database.py 中的不同预设。现在,让我们把这些都注释掉,使Masonite默认为SQLite3。
#DB_CONNECTION=mysql
#DB_HOST=127.0.0.1
#DB_PORT=3306
#DB_DATABASE=masonite
#DB_USERNAME=root
#DB_PASSWORD=root
#DB_LOG=True
现在,让我们运行一个迁移,迁移出开箱即用的默认用户授权迁移,并创建我们的SQLite3数据库。
craft migrate
接下来,让我们创建一个迁移,创建一个todos 表。
craft migration create_todos_table --create todos
上面的代码在databases/migrations ,生成了一个新的文件,看起来像下面的代码。
"""CreatePostsTable Migration."""
from masoniteorm.migrations import Migration
class CreatePostsTable(Migration):
def up(self):
"""
Run the migrations.
"""
with self.schema.create("todos") as table:
table.increments("id")
table.timestamps()
def down(self):
"""
Revert the migrations.
"""
self.schema.drop("todos")
up 函数代表我们运行迁移时发生的情况,而down 迁移代表我们回滚迁移或放弃表时发生的情况。接下来,让我们在up 函数中为todo 表添加一些字段。
def up(self):
"""
Run the migrations.
"""
with self.schema.create("todos") as table:
table.increments("id")
table.string("detail")
table.boolean("completed")
table.timestamps()
在上面的代码块中,我们添加了一个名为detail 的字符串字段和一个名为completed 的布尔字段。现在,让我们运行迁移并在数据库中创建表。
craft migrate
创建一个模型
现在,我们有了一个表,用于存放我们的Todos 。现在我们需要的是一个允许我们与数据交互的模型。
craft model Todo
让我们用我们的模型类创建文件app/Todo.py 。
"""Todo Model."""
from masoniteorm.models import Model
class Todo(Model):
"""Todo Model."""
pass
目前,我们所有的模型方法都是通过继承Masonite的Model 类而在Todo 类中获得的。
通常,表名是类名的复数,即:Dog 和Dogs 。虽然在我们的案例中,表应该自动工作,但让我们明确声明它应该连接的数据库表。
"""Todo Model."""
from masoniteorm.models import Model
class Todo(Model):
"""Todo Model."""
__table__ = 'todos'
在Python Shell中添加待办事项
运行下面的命令,打开一个带有预装Masonite容器的Python Shell。
craft tinker
然后,我们将导入我们的todo 模型,如下所示。
from app.Todo import Todo
现在,让我们通过多次添加下面的代码片断来创建一些待办事项。
Todo.create(detail="Hello", completed=False)
在你添加了几个待办事项之后,用quit() 退出 Python Shell 。现在,让我们把模型导入我们的控制器,并把所有这些待办事项以JSON格式发送回来。在你的app/http/controllers/FirstController.py 文件中添加下面的代码。
"""A FirstController Module."""
from masonite.request import Request
from masonite.view import View
from masonite.controllers import Controller
from app.Todo import Todo
class FirstController(Controller):
"""FirstController Controller Class."""
def __init__(self, request: Request):
"""FirstController Initializer
Arguments:
request {masonite.request.Request} -- The Masonite Request class.
"""
self.request = request
def show(self, view: View):
return Todo.all()
用craft serve 打开服务器,在localhost:8000/first 查看结果。
CORS
在部署我们的应用程序之前,我们需要设置我们的 CORS 标头,以防我们收到外部对我们应用程序的请求。
让我们导入并添加CORSProvider ,一个内置的提供者,帮助配置 CORS 中间件,到Providers 数组。添加以下代码块到/config/providers.py 。
"""Providers Configuration File."""
from masonite.providers import (
AppProvider,
CorsProvider, # ADD THIS
RequestHelpersProvider,
AuthenticationProvider,
BroadcastProvider,
CacheProvider,
CsrfProvider,
HelpersProvider,
MailProvider,
QueueProvider,
RouteProvider,
SessionProvider,
StatusCodeProvider,
UploadProvider,
ViewProvider,
WhitenoiseProvider,
)
from masonite.logging.providers import LoggingProvider
from masonite.validation.providers import ValidationProvider
from masoniteorm.providers import ORMProvider
"""Providers List
Providers are a simple way to remove or add functionality for Masonite
The providers in this list are either ran on server start or when a
request is made depending on the provider. Take some time to can
learn more more about Service Providers in our documentation
"""
PROVIDERS = [
# Framework Providers
AppProvider,
CorsProvider, # ADD THIS
RequestHelpersProvider,
CsrfProvider,
AuthenticationProvider,
SessionProvider,
RouteProvider,
StatusCodeProvider,
WhitenoiseProvider,
ViewProvider,
# Optional Framework Providers
MailProvider,
UploadProvider,
QueueProvider,
CacheProvider,
BroadcastProvider,
HelpersProvider,
ValidationProvider,
# Third Party Providers
LoggingProvider,
ValidationProvider,
ORMProvider,
# Application Providers
]
配置 CORS 中间件
为了配置我们的 CORS 中间件,首先,让我们声明一个 CORS 变量,并给它分配一个我们的cors 头文件的字典。将下面的代码添加到你的/config/middleware.py 文件中。
"""Middleware Configuration Settings."""
from masonite.middleware import (
ResponseMiddleware,
MaintenanceModeMiddleware,
GuardMiddleware,
)
from app.http.middleware.AuthenticationMiddleware import AuthenticationMiddleware
from app.http.middleware.CsrfMiddleware import CsrfMiddleware
from app.http.middleware.LoadUserMiddleware import LoadUserMiddleware
from app.http.middleware.VerifyEmailMiddleware import VerifyEmailMiddleware
"""HTTP Middleware
HTTP middleware is middleware that will be ran on every request. Middleware
is only ran when a HTTP call is successful (a 200 response). This list
should contain a simple aggregate of middleware classes.
"""
HTTP_MIDDLEWARE = [
LoadUserMiddleware,
CsrfMiddleware,
ResponseMiddleware,
MaintenanceModeMiddleware,
]
"""Route Middleware
Specify a dictionary of middleware to be used on a per route basis here. The key will
be the alias to use on routes and the value can be any middleware class or a list
of middleware (middleware stacks).
"""
ROUTE_MIDDLEWARE = {
"auth": AuthenticationMiddleware,
"verified": VerifyEmailMiddleware,
"guard": GuardMiddleware,
}
## ADD THIS
CORS = {
'Access-Control-Allow-Origin': "*",
"Access-Control-Allow-Methods": "*",
"Access-Control-Allow-Headers": "*",
"Access-Control-Max-Age": "3600",
"Access-Control-Allow-Credentials": "true"
}
将我们的Masonite应用程序部署到Heroku
为了将我们的Masonite待办事项列表应用部署到Heroku,首先,让我们安装Gunicorn和Psycopg2。如果你没有使用Heroku postgres,请确保为你的部署平台安装正确的驱动程序。
pip install psycopg2
pip install gunicorn
在项目根目录下创建一个名为Procfile 的文件,并运行以下命令。
web: gunicorn wsgi
接下来,创建一个runtime.txt 文件。
python-3.9.0
要创建当前依赖的列表,运行pip freeze > requirements.txt 。
backpack==0.1
bcrypt==3.1.7
certifi==2021.5.30
cffi==1.14.6
charset-normalizer==2.0.5
cleo==0.8.1
clikit==0.6.2
crashtest==0.3.1
cryptography==3.4.8
exceptionite==1.0.1
Faker==4.18.0
gunicorn==20.1.0
hfilesize==0.1.0
hupper==1.9.1
idna==3.2
inflection==0.3.1
Jinja2==2.11.3
MarkupSafe==2.0.1
masonite==3.0.12
masonite-dot==0.0.5
masonite-logging==1.0.1
masonite-orm==1.0.55
masonite-validation==3.0.14
passlib==1.7.4
pastel==0.2.1
pendulum==2.1.2
psutil==5.6.7
psycopg2==2.9.1
pycparser==2.20
pylev==1.4.0
python-dateutil==2.8.2
python-dotenv==0.10.5
pytzdata==2020.1
requests==2.26.0
requests-file==1.5.1
simplejson==3.17.5
six==1.16.0
tabulate==0.8.9
text-unidecode==1.3
tldextract==2.2.3
urllib3==1.26.6
whitenoise==4.1.4
如果你缺少上述任何一个依赖项,或者你在使用Psycopg2时遇到问题,你可以轻松地将缺少的依赖项复制到你的requirements.txt 文件中。
接下来,我们将把我们的项目推送到GitHub上,并部署到一个新的Heroku项目。进入 "资源"选项卡,配置一个Heroku postgres数据库。获取数据库的凭证,并在Herokuconfig vars 中添加以下变量。
DB_CONNECTION=postgres
DB_HOST=<get value from herok>
DB_PORT=<get value from herok>
DB_DATABASE=<get value from herok>
DB_USERNAME=<get value from herok>
DB_PASSWORD=<get value from herok>
DB_LOG=True
最后,从你的本地.env ,将key 变量复制到你的Herokuconfig vars ,并设置一个变量。我们最终应用程序的代码看起来如下图所示。
结论
在本教程中,我们用Masonite建立了一个简单的待办事项列表应用程序,这是一个使用MVC模型的Python网络框架。Masonite 提供了许多现代框架(如 PHP、Ruby 和 NextJS)的最佳功能,并将它们以一个光滑的包带入 Python。
CLI通过帮助你生成你的应用程序的组件,同时还提供了足够简单的工作流程,以最大限度地提高生产力。现在你已经熟悉了Masonite的基本原理,你应该能够建立你自己的、复杂的应用程序。编码愉快!
The postMasonite:Python的MVC网络框架首次出现在LogRocket博客上。