前回はMasoniteについて簡単に概要を説明しました。今回はより実践的な内容にまで踏み込んでいきます。Laravelとの徹底比較はまた後日()
LaravelそっくりなPython製WebフレームワークMasoniteの紹介
さて、メインのフレームワークにMasoniteを使っていくわけですが、今までずっと(プライベートでは)Djangoを使ってきた私にとっては、自動生成される管理画面と、モデルを書けばそのままSchemaになるDjangoのモデルの思想は、他のどのフレームワークよりも便利なものでした。
しかしMasoniteの良さは、私が仕事で使ってきたLaravelやRailsと同じくMVCフレームワークである点や、Oratorを使って複雑にリレーションを張ったRDBからの値を取得できる点、ReactやVueなどフロント側のモダンな技術との連携の容易さ、Restfulにコントローラーを作れることなどにあると思います(このテーマについては別で掘り下げようと思います)
ということで、MasoniteとDjangoのいいとこどりの構成でやっていきます!
具体的には
- Djangoでモデルを作る
- Djangoでマイグレーションファイルを作る(自動)
- Djangoでマイグレートする
- Djangoの管理画面を使う
- MasoniteでDBアクセス、ルーティング、リクエストとレスポンスのやり取りを行う
- フロント側のファイルはMasoniteのプロジェクト内に作る
という構成でやっていきたいと思います。
今回は、Djangoの管理画面からウェブサイトのトップページの内容を投稿し、Masoniteを使ってトップページの内容を取得し、Reactで作った画面と共にクライアントに返却する、というものを作っていきます。
プロジェクトを作る
anyenv→pyenv→venv→pipenvの構築は前回の記事と同じです。
MasoniteとDjangoをインストール。
pipenv install masonite-cli django
Masoniteのプロジェクトを作ります。
craft new project
cd project
craft install #依存パッケージがインストールされる
次にDjangoのプロジェクトを作ります。
MysqlやPgsqlなどのRDBを使う場合は、DjangoもMasoniteもそれぞれソケットを通じてRDBと接続するので、プロジェクトを並列に作ってもいいのですが、今回はSqliteを使うので、Masoniteの中にDjangoのプロジェクトをadminディレクトリとして作ります。
django-admin startproject admin
cd admin
python manage.py startapp my_site
現在のディレクトリ構成は以下のようになったと思います。
project ←Masoniteのプロジェクト
admin ←Djangoのプロジェクト
admin
setting.py
urls.py
wsgi.py
my_site
migrations
admin.py
app.py
models.py
test.py
views.py
manage.py
app
bootstrap
config
databases
resources
routes
storagetest
.env
wsgi.py
Django
モデルを作る
ではプロジェクトの設計に入ります。Djangoでモデルを作っていきます。
from django.db import models
class Toppage(models.Model):
def __str__(self):
return str(self.title)
title = models.CharField(max_length=255)
article = models.TextField(blank=True, null=True)
class Meta:
db_table = 'toppage'
verbose_name_plural = 'toppage'
Djangoはマイグレートすると、テーブル名にアプリ名のプレフィックスが付く仕様になっています。それを防ぐためにclass Metaでdb_tableを設定します。
verbose_name_pluralは複数形の時のテーブル名を表します。管理サイトのテーブル名として表示されます。
def __str__(self):
return str(self.title)
これもDjangoの管理サイトで、テーブル内の列名として表示されるものを正しくタイトルを表示するために設定しています。
マイグレート
my_siteのモデルの変更をDjangoに認識してもらうために、setting.pyを編集します。
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'my_site', #←追加
]
マイグレートします
cd /project/admin
python manage.py makemigrations
python manage.py migrate
モデルの変更を自動で感知してマイグレーションファイルを作ってくれるの!!!すごく便利!!!
あとは管理者ユーザーを作って、Djangoを起動すると管理サイトが開きます。
python manage.py createsuperuser
python manage.py runserver
React
Reactでフロント側を作ります。今回はサラッと
Masoniteでは、ビューのファイルは/project/resources/templatesの中に作られるわけですが、その中でcreate-react-appコマンドを実行することで、MVCの形を維持したままReactのプロジェクトを作ることができます。もちろん、「vue create」でも同じようにできると思います。
cd /project/resources/templates
npm install yarn
yarn add global create-react-app
create-react-app my_site
cd my_site
yarn add axios
App.jsに、サーバーとAPI通信し、画面に表示する処理を作ります。
import React, { Component } from 'react';
import axios from 'axios';
export default class App extends Component {
state = {
toppage: '',
}
getToppage=()=>{
axios.get('/my-site/api/get_toppage')
.then(response=>{
this.setState({
toppage: response.toppage;
})
})
.catch(e=>{
console.error('通信エラー');
})
}
componentDidMount(){
this.getToppage();
}
render(){
return(
<div>
{this.state.toppage}
</div>
);
}
}
コンパイルします
yarn build
するとコンパイルされたファイルが /project/resources/templates/my_site/build/ に作られます。
ひとまずMasoniteに「/static」にアクセスが来たときに、「/project/resources/templates/my_site/build/static/」ディレクトリを見に行くよう設定します。
index.htmlの配信は後ほど。
STATICFILES = {
# folder # template alias
'resources/templates/my_site/build/static': 'static/', #←追加
'storage/static': 'static/',
'storage/compiled': 'static/',
'storage/uploads': 'static/',
'storage/public': '/',
}
Masonite
ここからMasoniteでMVCを作っていきます。
まずはDjangoが作った/project/admin/db.sqlite3のファイルを、Masoniteが読めるようにしましょう。.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=sqlite
DB_DATABASE=admin/db.sqlite3
DB_LOG=True
モデルを作る
Masoniteでモデルを作ります。
cd /project
craft model models/Topppage
トップページの内容をコントローラーに返すメソッドを作ります。
from config.database import Model
class Toppage(Model):
__table__ = 'toppage'
@staticmethod
def get_toppage():
return Toppage \
.select(
'title',
'article'
) \
.find(1) \
.serialize()
「__table__ = 'toppage'」を設定することで、Masoniteはテーブル名がtoppageのテーブルを見に行きます。
Masoniteが採用しているPythonのActiveRecordであるOratorの仕様ですが、serialize()をつけないとクラスとして、つけるとdictとして取得できます。
コントローラーを作る
craft controller Toppage
/project/app/http/controllers/ToppageController.pyが作られます。
htmlを返すルートと、トップページの内容を返すAPIに対応したメソッドを作ります。
from app.models.Toppage import Toppage
class ToppageController:
def show(self):
return view('my_site/build/index.html')
def get_toppage(self):
toppage = Toppage.get_toppage()
return {'toppage': toppage}
コントローラーのviewメソッドは、「/project/resources/templates/」を見に行くように自動で設定されています。
ルーティングを作る
htmlを返すルートと、トップページの内容を返すAPIに対応したルートを作ります。
from masonite.helpers.routes import get
from app.http.controllers.ToppageController import ToppageController
ROUTES = [
get('/', ToppageController.show),
get('/my-site/api/get_toppage', ToppageController.get_toppage)
]
以上でサーバー側処理は終わりです。
インフラ
ここからサーバーの設定をします。
サーバーに初めから入っているPythonのバージョンが古かったり、自分で好きなバージョンを使いたかったりすると思うので、サーバーの中も同じくanyenv→pyenv→venv→pipenvの順番で環境構築するといいでしょう。
では初めに、Djangoの静的ファイルを配信する設定を書きます。
STATIC_URL = '/static/'
STATIC_ROOT = os.path.join(BASE_DIR, 'templates/static')
静的ファイルをまるっと配信用ディレクトリに持ってきましょう。Djangoの組み込みコマンドが使えます。
python manage.py collectstatic
Nginx
Nginxをインストールしましょう。
apt install nginx
インストール終了後に、サーバーのIPアドレス80番ポートにアクセスすると、「Welcome Nginx!」のページが見えていると思います。
- 「/admin」にアクセスした時はDjangoの管理画面
- 「/static/admin」にアクセスしたときはDjangoの管理画面で使う静的ファイル
- それ以外のアクセスはMasoniteで受け止める
ように設定していきます。
ファイルのhttpディレクティブ内に書きます
upstream django {
server unix:///var/run/django.sock;
}
upstream masonite {
server unix:///var/run/masonite.sock;
}
server {
listen 80;
server_name my_site.com;
location /static/admin {
alias /path/to/your/site/project/admin/templates/static/admin;
}
location /admin {
uwsgi_pass django;
include /path/to/your/site/project/admin/uwsgi_params;
}
location / {
uwsgi_pass masonite;
include /path/to/your/site/project/project/uwsgi_params;
}
}
/etc/nignx/のディレクトリにuwsgi_paramsというファイルがあるので、これをMasoniteとDjango、それぞれのプロジェクトルートへコピーしましょう。
cp /etc/nginx/uwsgi_params /path/to/your/site/project/project/
cp /etc/nginx/uwsgi_params /path/to/your/site/project/project/admin
uwsgi
uwsgiとは、Pythonの本番環境でよく使われるアプリケーションサーバーのためのアプリです。gunicornも同じくPython製アプリケーションサーバーとして共によく使われます。
まずはuwsgiをインストールします
pipenv install uwsgi
uwsgiの設定を書いたiniファイルを作ります。
[uwsgi]
socket = /var/run/django.sock
# permissions for the socket file
chmod-socket = 666
# application's base folder
base = /path/to/your/site/project/admin
# python module to import
module = admin.wsgi
processes = 2
threads = 1
[uwsgi]
socket = /var/run/masonite.sock
# permissions for the socket file
chmod-socket = 666
# application's base folder
base = /path/to/your/site/project
# python module to import
module = wsgi
processes = 2
threads = 1
サービスの起動方法ですが、uwsgiはpipなどと同じく、コマンドで起動するPythonで作られたアプリなので、Masoniteは/project、Djangoは/project/adminとそれぞれの場所で立ち上げなくていけません。これは起動バッチを作るのが良いでしょう。
nohupと &を使って、バックグラウンドで実行するようにしています。
# !/bin/bash
service nginx restart
nohup uwsgi --ini masonite.ini > /dev/null 2>&1 &
# !/bin/bash
nohup uwsgi --ini django.ini > /dev/null 2>&1 &
サービス停止するときは
killall uwsgi
ではサービスを起動しましょう!かならずvenvを有効にしてください。
cd /path/to/your/site/
source .venv/bin/activate # venvを有効にしないとuwsgiにパスが通らない
cd project/
./run.sh
cd admin/
./run.sh
ブラウザからサーバーの「/admin」にアクセスするとDjangoの管理画面が、「/」にアクセスすると、Reactで作った画面が開き、Django管理画面から投稿した内容がMasoniteから配信されて画面に表示されていれば成功です。
最後に
今回はDjangoの管理画面とMasoniteでサービス運用する手順、モダンなフロント技術との連携、本番デプロイまで、一気に説明しました。
これを機に、より多くのがPythonでウェブ開発をする楽しさ、効率の良さに気づいていただけたら、またPythonistaもMasoniteを触っていただけたらと思います!
ありがとうございました。