2019年あけましておめでとうございます!!!
私は今年はPHPの大人気フレームワークLaravelそっくりのPython製フレームワークであるMasoniteを広めていきたいなーと考えています。Laravelの素晴らしいディレクトリ構造、フルスタックFWのパワフルさ、そしてPythonの可読性の高さ、書きやすさのミックスされたフレームワークは使いやすいこと間違いなし!
ということで第一弾、Masoniteフレームワークの紹介!まずは環境構築から!
Pythonのインストール
Pythonのインストールについては、個人的にはanyenvとpyenvを使ってするのが便利だと思います。やり方はこちらをご覧ください。
anyenvインストール
pyenvインストール
↓
anyenv install pyenv
exec $SHELL -l # bashを更新
pyenv install 3.6.6 # Python3.6.6をインストール
pyenv local 3.6.6 # ディレクトリ内でPythonへのパスを3.6.6へ通すように設定する
venv環境を作る
venvとは、プロジェクト毎で使うPythonパッケージを、ローカルに隠蔽するためのものです。
JavaScriptで言うnode_modules、Laravel、Railsのvendorディレクトリのようなものです。
# .venvにvenv環境のディレクトリを作る
python -m venv .venv
# venvを有効化
source .venv/bin/activate
プロジェクトで使用するPythonパッケージの管理には、pipenvを使います。pipfile、pipfile.lockというファイルにPythonパッケージの一覧を記録して、それを介して複数の開発者が同じパッケージを楽にインストールできるようにする仕組みです。JavaScriptのpackage.json、RubyのGemfileと同じような仕組みのものです。
# pipenvをインストール
pip install pipenv
これでpipenvコマンドが使えるようになります。
Masoniteをインストール
pipenv install masonite-cli
masonite-cliをインストールすると、craftコマンドが使えるようになります。このコマンドを使うことで、php artisanコマンドや、railsコマンドのように、コントローラーを作ったりモデルを作ったり開発サーバーを起動したりができます。
プロジェクトを作る
craft newコマンドで、プロジェクトを作ります。例ではプロジェクト名をprojectとしています。ここは任意に好きな名前を付けてください。
craft new project
# projectディレクトリ以下に移動
cd project
# Masoniteが使うパッケージ類をインストール
craft install
これでプロジェクトを起動する準備が整いました!serveコマンドでブラウザから見てみましょう。
craft serve
いかがでしょうか。 Laravelそっくりですね笑
Masoniteフレームワークの紹介
ではここからは、フレームワーク自体について紹介していきます。
PythonのウェブフレームワークといえばDjangoが有名ですが、DjangoはMTV構造なのに対して、Masoniteは完全にLaravel、Railsを同じMVC構造を持っています。
また、モデルに関してはLaravelを同じ考え方を採用していて、Railsがmodelsディレクトリがあるのに対して、Masoniteにもmodelsディレクトリはありません。もちろんmodelsディレクトリを作る使い方もできます。
ディレクトリ構造
ほぼLaravelと同じだと思ってもらって大丈夫だと思います。
長いので折りたたみ
project
app
http
controllers
WelcomeController.py
middleware
AuthenticationMiddleware.py
CsrfMiddleware.py
LoadUserMiddleware.py
VerifyEmailMiddleware.py
providers
User.py
bootstrap
config
application.py
auth.py
broadcast.py
cache.py
database.py
mail.py
middleware.py
packages.py
providers.py
queue.py
session.py
storage.py
database
migrations
seeds
database_seeder.py
user_table_seeder.py
resources
templates
welcome.html
routes
web.py
storage
compiled
style.css
public
static
sass
style.scss
uploads
tests
feature
test_feature_works.py
test_imports.py
unit
test_works.py
.env
requirement.txt
wsgi.py
ルーティング
ルーティングはproject/routes/web.pyに書きます。
Djangoではgetとpostなどはルーティングで切り替えられませんが、MasoniteではHTTP動詞に対応してルートを定義できるようにしています。
from masonite.routes import Get, Post
ROUTES = [
Get().route('/', 'WelcomeController@show').name('welcome'),
]
Laravelに慣れている人ならこの意味はすぐに理解できると思います。ルートにgetでアクセスした時に、WelcomeConstollerのshowメソッドを呼びだす、という意味です。
また、クラスとメソッドを文字列でハードコーティングしたくない!という人のために、コントローラーのクラスとメソッドをimportして使うこともできます。こちらはよりDjangoのurls.pyと近い感覚で使えると思います。
from masonite.routes import Get, Post
from app.http.controllers.WelcomeController import WelcomeController
ROUTES = [
Get().route('/', WelcomeController.show)
]
ルートオプション
http動詞の指定には、関数型っぽく書けるmasonite.routesと、省略形のメソッドであるmasonite.helpers.routesの2つから選べます
from masonite.routes import Get
from app.http.controllers.WelcomeController import WelcomeController
ROUTES = [
Get().route('/', WelcomeController.show)
]
from masonite.helpers.routes import get
from app.http.controllers.WelcomeController import WelcomeController
ROUTES = [
get('/', WelcomeController.show)
]
ルーティンググループ
さらにルーティングにグループを設定することができます。Djangoのルーティンググループの作り方と比較してみましょう。
hoge/aaaにアクセス→aaaメソッドが呼ばれる
hoge/bbbにアクセス→bbbメソッドが呼ばれる
hoge/cccにアクセス→cccメソッドが呼ばれる
Django
from django.urls import include, path
from . import views
hoge_paterns = [
path('aaa', views.hoge_views.aaa),
path('bbb', views.hoge_views.bbb),
path('ccc', views.hoge_views.ccc)
]
urlpatterns = [
path('hoge/', include(hoge_paterns))
]
Masonite
from masonite.helpers.routes import get
from app.http.controllers.HogeController import HogeController
ROUTES = [
RouteGroup([
get('/aaa', HogeController.aaa),
get('/bbb', HogeController.bbb),
get('/ccc', HogeController.ccc),
], prefix='/hoge')
]
コントローラー
ではcraftコマンドを使って、コントローラーを作ってみましょう。Djangoの人はこれは初体験、LaravelとRailsの人は慣れたことだと思います。
# Laravelの場合
php artisan make:controller SomeController
# Railsの場合
bundle exec rails g controller Some
# Masoniteの場合
craft controller Some
project/app/http/controllers/SomeControllers.pyが自動生成されます。
class SomeController:
"""SomeController
"""
def show(self):
pass
次のように、コマンドに「-r」のコマンド引数を追加することで、CRUDに対応したアクションメソッドが自動生成されます。Railsのscaffold_controllerと似ていますね。
# Railsの場合
bundle exec rails g scaffold_controller Some
# Masoniteの場合
craft controller Some -r
自動生成されたコントローラーは長いので折りたたみ
""" A SomeController Module """
class SomeController:
"""Class Docstring Description
"""
def show(self):
"""Show several resource listings
"""
pass
def index(self):
"""Show a single resource listing
"""
pass
def create(self):
"""Show form to create new resource listings
"""
pass
def store(self):
"""Create a new resource listing
"""
pass
def edit(self):
"""Show form to edit an existing resource listing
"""
pass
def update(self):
"""Edit an existing resource listing
"""
pass
def destroy(self):
"""Delete an existing resource listing
"""
pass
ビューを返すにはviewメソッドをreturnします
def show(self):
return view('some')
project/resources/templates/some.htmlが返されます。
また、dict型をreturnすると、Jsonを返すことができます。
def show(self):
return {'key': 'value'}
ビュー
ビューもコマンドで作ることが出来ます。
craft view some
project/resources/templates/some.htmlが自動生成されます。
テンプレートエンジンにはJinja2が使われています。これはFlaskでの開発で人気がありますね。
コントローラーでviewメソッドの第二引数にdict型を設定して、ビューに変数を渡します。
コントローラー
def show(self):
return view('some', {'world': 'world'})
ビュー
<p>Hello {{ world }}</p>
モデル
テーブルを作るには、craftコマンドを使って、始めにマイグレーションファイルを作ります。
次のようなツイッターのpostのような簡単な構造のテーブルを作ってみましょう。
postテーブル
英語名 | 日本語名 | 型 | null許可 | 説明 | 外部キー |
---|---|---|---|---|---|
id | id | int | x | --- | --- |
post | 投稿 | text | x | --- | --- |
user_id | ユーザーID | int | x | 投稿者のID | User.id |
timestamp | タイムスタンプ | int | x | 投稿日時 | --- |
craft migration create_post_table --create posts
project/databases/migrations/2018_12_31_185839_create_post_table.pyが自動生成されます。
ではここにテーブル構造を作っていきましょう。
Masoniteでは、データベース周りは全て、OratorというLaravelのORMライクなアクティブレコードベースのPythonのライブラリを採用しています。マーグレーションファイルの書き方も、ORMも全てOratorの書き方に従います。これは一部Flaskで使っている人もいるようですが…
Orator
from orator.migrations import Migration
class CreatePostTable(Migration):
def up(self):
"""
Run the migrations.
"""
with self.schema.create('posts') as table:
table.increments('id')
table.long_text('post')
table.integer('user_id').unsigned()
table.foreign('user_id').references('id').on('users')
table.timestamps()
def down(self):
"""
Revert the migrations.
"""
self.schema.drop('posts')
そしてcraftコマンドでマイグレートします
craft migrate
マイグレートできたら、craftコマンドを使ってモデルを作ります。この時に「models/」を含めることで、modelsディレクトリも一緒に作られます。
craft model models/Post
project/app/models/Post.pyが自動生成されました。
このモデルの中では、バリデーションルールや、テーブルからデータをやり取りする純粋なビジネスロジックを書き、コントローラーから呼び出すようにします。
from config.database import Model
class Post(Model):
__fillable__ = ['post', 'user_id']
まとめ
以上でMasoniteフレームワークの紹介を終わります。
公式ドキュメントは全て英語で書かれていますが、とても簡単な英語で書かれているのでぜひ挑戦してみてください。また、簡単なチュートリアルも載っています。
公式ドキュメント
いかがでしたでしょうか、今までLaravelを使っていた人も、Railsを使っていた人も、これを機会にPythonでウェブを作るということを検討してみても面白いと思います。
Pythonを実行するインタープリターを、普通のPythonではなくPypyを使うことで、全く同じソースコードのままGo言語の80%ほどの速度が出せるほど高速化することもできます。
Pythonでウェブを作り、ゲームを作り、ドローンを飛ばし、データ解析をし、機械学習をする。Pythonは本当に簡単に書けて、簡単に読めて、幅広く使える、素晴らしいプログラミング言語だと感じています。
次回はLaravelとMasoniteで全く同じものを同時進行で作り、2つのフレームワークを徹底比較してみたいと思います。こうご期待!