Edited at

LaravelそっくりなPython製WebフレームワークMasoniteの紹介

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

Screenshot from 2018-12-31 23-14-01.jpg

いかがでしょうか。 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つから選べます

HTTP Verbs

from masonite.routes import Get

from app.http.controllers.WelcomeController import WelcomeController

ROUTES = [
Get().route('/', WelcomeController.show)
]

HTTP Helpers

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つのフレームワークを徹底比較してみたいと思います。こうご期待!