この記事の内容
この記事では、Django製のWebアプリケーションを作り、自分のローカルPCでブラウザからつないで見るところまで進めます。
(ずっとターミナルでコマンドを打ち込み、いろいろインストールしたり何かを自動で構築したりということが進みます)
全体像で見てみると、この緑色で囲った部分が対象です。
ターミナルとは
- Homebrewのインストール
- Python3のインストール
- Virtualenvで仮想環境を作る
- Django(Pinax)を使ってWebアプリケーションを構築
- npmでフロント周りの静的ファイルを生成
ということをやっていきます。
Homebrewのインストール
後ほどPython3をインストールするのですが、そのためにHomebrewというMacOS用のパッケージマネージャーが必要になるので、それを先にインストールします。コマンドは公式サイト通りです。
$ /usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"
ターミナルにコマンドをコピペするとき
パッケージマネージャーとは
何かを作るときは、いろいろなパッケージ(ライブラリ)を駆使しながら進めていきます。その時にそれらパッケージ(ライブラリ)を簡単にインストール・アップデート・アンインストールできるようにする管理ツールが必要になってきて、このことをパッケージマネージャー(パッケージ管理)と呼びます。 Homebrewの他にも、Pythony用パッケージマネージャーのpip、CentOSで使うyumなど様々なものがあります。Python3のインストール
Pythonのバージョンは2系と3系で構文の書き方が違ったり利用できるライブラリが異なったりします。そのため目的に応じてPythonのバージョンを使い分けられる必要がででき、アプローチとしては、
- 元々macに入っている2系に加えて3系をインストールして、別々のコマンドで使い分けるという方法 (今回はこちらで説明します。)
- pyenvという複数バージョンのPythonを簡単に切り替えることができるライブラリを用いる方法
があります。
MacにはPython2系が予めインストールされています。それを確認してみましょう。
$ python -V
Python 2.7.10
どこにインストールされているかも見てみます。
$ which python
/usr/bin/python
それでは、Python3系をHomebrewでインストールします。
$ brew install python3
これで最新版のPython3が入ります。バージョンとインストール先を確認します。
$ python3 -V
Python 3.6.5
$ which python3
/usr/local/bin/python3
Virtualenvで仮想環境を作る
続いて、VirtualenvというPythonの仮想的な環境を作るためのパッケージを使って、今回作成するTODOアプリ専用の環境を作成します。
例えば2つのPython製アプリケーションを開発している場合に、一方は特に制約なく最新バージョンのPythonを利用できる、しかしもう片方は最新バージョンのPythonに対応していないライブラリを利用しないといけない、といったことがあります。
こういった場合に、Pythonのバージョンやインストールしたライブラリ群が異なる環境をわけて作ることで、2つのアプリを共存させられるようになります。
まず、VirtualenvをpipというPython用のパッケージマネージャーを使ってインストールします。
$ pip install virtualenv
そして、これから作成してくTODOアプリのための作業ディレクトリを作成します。
$ mkdir todo
作成したディレクトリに移動します。
$ cd todo
virtualenvのコマンドで先ほどインストールしたPython3を指定して環境を作成します。
はじめにhomebrewでPython3をインストールした際にコマンドのパスが通ったので、そのコマンドを利用してPythonのバージョンを指定します。
$ virtualenv -p python3 todo_env
これでtodo_env
という名前のTODOアプリ専用の仮想環境ができました。これを起動します。
$ source todo_env/bin/activate
ターミナルでユーザー名の頭に(todo_env)
というものが付いたと思います。これが仮想環境の中にいるということを意味しています。
それでは、さっきと同様にPythonのバージョンを確認してみます。
$ python -V
Python 3.6.5
さきほどインストールしたPython3系が利用されています。
ここまでで何を作ったのかは下図のような感じです。
MacOSにはPython2とPython3を別々にインストールし、それぞれpython
、python3
というコマンドで呼び出せるようにしました。そしてtodo_env
という仮想環境を作るときに、Python3の方を利用するように指定しました。
なので図のようにこの他にも仮想環境を作り、適したバージョンのPythonを適用することができます。
なお、この仮想環境を終了する場合はdeactivate
コマンドを使います。
$ deactivate
Django(Pinax)を使ってWebアプリケーションを構築
ようやくDjangoを使ってWebアプリケーションを作っていきます。ここでDjangoとPinaxに関して軽く触れます。
Django
DjangoはPython製のWebフレームワークです。2005年にリリースされたもので結構歴史が長く、Python製Webフレームワークの中ではかなり有名です。
The Top Web Development Frameworks in 2018 によると、
- Djangoは早い開発スピードを実現する
- Djangoはセキュリティ面に優れている
- Djangoはスケーラブルで、トラフィックの増加に対応しやすい
- Djangoは全ての機能が搭載されている
と書かれています。デフォルトの機能、また様々なDjango用のライブラリが豊富だったりDjangoプロジェクトがあるため、こんなことをやりたいというときにはかなりサクサク要望を実現できます。
例えば『スマホアプリでも利用できるようにしたいのでAPIを作りたい』といったものや、『Q&Aページを作ってユーザーの問い合わせを効率的に管理したい』といったものなど探すと結構出てきます。
Webフレームワークとは
Pinax
Pinaxは有志が作っているDjango製のアプリケーションの雛形で、Webでよく使われる機能があらかじめ含まれたプロジェクトです。これを使ってDjangoのWebアプリケーション開発を始めることで、かなり効率的に進められるようになります。
ものを見たほうが早いので、実際に使っていきます。
まず、Pinaxのコマンドラインインターフェイスをpipでインストールします。
$ pip install pinax-cli
これでpinaxのプロジェクトを利用する準備ができました。どんなプロジェクトがあるか見ていきます。
$ pinax projects
Release Project
------- ---------------
4.0.4 account
4.0.4 blog
2.0.4 company
documents
social-auth
4.0.4 static
4.0.4 stripe
team-wiki
3.0.4 waitinglist
wiki
4.0.4 zero
利用可能なプロジェクトの一覧が表示されています。ここで言うプロジェクトの実のところは、作りたいWebアプリケーションごとに必要な機能が用意されたDjangoプロジェクトです。いくつか見ていくと、
- account : 会員管理系のサイト用プロジェクトです。会員登録・ログイン・ログアウト・退会といった機能があります。
- wiki : wikiサイト用のプロジェクトです。権限を受けたユーザーがwikiページを投稿できるといった機能があります。
- stripe : 課金サービス系のサイト用プロエクとです。決済サービスのstripeと連携する機能があります。
などがあります。もっと詳しくは [Pinax Starter Projects] (http://pinaxproject.com/pinax/pinax_starter_projects/#starter-project-list) を御覧ください。
今回はオーソドックスなaccount
を利用します。アプリケーションの名前はtodo
とします。
$ pinax start account todo
TODOアプリのプロジェクトが生成されたので、ディレクトリの中に入ります。
$ cd todo
このプロジェクトを動かすためのライブラリを今の仮想環境にインストールします。インストールが必要なライブラリはこのディレクトリの中にあるrequirements.txt
というファイルに定義されています。
$ pip install -r requirements.txt
どんなものがインストールされたのか見てみます。
$ pip list
Package Version
--------------------- ---------
certifi 2018.4.16
chardet 3.0.4
click 6.7
colorama 0.3.9
crayons 0.1.2
Django 2.0.6
django-appconf 1.0.2
django-bootstrap-form 3.4
django-user-accounts 2.0.3
idna 2.6
jsonfield 2.0.2
pinax-cli 1.1.4
pinax-eventlog 2.0.3
pinax-templates 2.0.1
pinax-webanalytics 4.0.2
pip 10.0.1
pytz 2018.4
requests 2.18.4
setuptools 39.2.0
urllib3 1.22
wheel 0.31.1
Django
やユーザー管理用のdjango-user-accounts
がインストールされているのがわかります。
次に、このアプリケーションで使うデータベースのテーブルを作ります。
なお、ここからmanage.py
というファイルを経由してコマンドを実行していきます。これらは全てDjangoが用意しているコマンドです。
$ python manage.py migrate
Operations to perform:
Apply all migrations: account, admin, auth, contenttypes, eventlog, sessions, sites
Running migrations:
Applying contenttypes.0001_initial... OK
Applying auth.0001_initial... OK
Applying account.0001_initial... OK
Applying account.0002_fix_str... OK
Applying account.0003_passwordexpiry_passwordhistory... OK
Applying account.0004_auto_20170416_1821... OK
Applying admin.0001_initial... OK
Applying admin.0002_logentry_remove_auto_add... OK
Applying contenttypes.0002_remove_content_type_name... OK
Applying auth.0002_alter_permission_name_max_length... OK
Applying auth.0003_alter_user_email_max_length... OK
Applying auth.0004_alter_user_username_opts... OK
Applying auth.0005_alter_user_last_login_null... OK
Applying auth.0006_require_contenttypes_0002... OK
Applying auth.0007_alter_validators_add_error_messages... OK
Applying auth.0008_alter_user_username_max_length... OK
Applying auth.0009_alter_user_last_name_max_length... OK
Applying eventlog.0001_initial... OK
Applying eventlog.0002_auto_20150113_1450... OK
Applying eventlog.0003_auto_20160111_0208... OK
Applying sessions.0001_initial... OK
Applying sites.0001_initial... OK
Applying sites.0002_alter_domain_unique... OK
ここで行ったのは『マイグレーション』という処理です。DjangoにはModel
というデータベースの定義を『マイグレーションファイル』として作成して、それのファイルをもとにその定義のテーブルを作るという機構があります。
なのでここではaccount
プロジェクトで定義されていたファイルを読み込んで、テーブルが生成されました。
今はまだテーブルにデータが入っていない状態ですが、次のコマンドで最低限のサイト情報を取り込みます。
$ python manage.py loaddata sites
fixtures/sites.json
の定義を基にデータをロードする処理が行われ、データが作られました。
今作られたデータを見てみたいので、管理画面にログインするために管理者用のアカウントを作ります。これもDjangoに予め用意されている機能が利用できます。
ここでは任意のUsername
、Email address
、Password
を入力します。
今回はUsername
はuser
とし、Email address
は必須ではないので未入力で進めます。
$ python manage.py createsuperuser
Username (leave blank to use 'user'): user
Email address:
Password:
Password (again):
Superuser created successfully.
パスワードは表示されません
サーバーを起動します。
Djangoには開発用のサーバーが用意されているので、わざわざApacheなどWebサーバーを立てなくても動作の確認ができます。
$ python manage.py runserver
Performing system checks...
System check identified no issues (0 silenced).
June 03, 2018 - 07:20:28
Django version 2.0.6, using settings 'todo.settings'
Starting development server at http://127.0.0.1:8000/
Quit the server with CONTROL-C.
サーバーが起動されました。ブラウザからhttp://localhost:8000/admin/login/?next=/admin/
にアクセスしてみます。
管理画面にアクセスできました。この管理画面はDjangoの特徴の一つで、データベースに接続しなくてもブラウザからデータの閲覧・作成・編集・削除ができるものです。
実際に処理が反映されたかどうか、データベースを見に行くみたいな手間が省けてかなり良いです。
先程登録したuser
とパスワードでログインすると、このアプリケーションで管理している情報を見ることができます。一番下にあるSites
というリンクからhttp://localhost:8000/admin/sites/site/
にアクセスすると、サイトのレコードが2つ登録されてるのがわかると思います。これが先程loaddata
コマンドで作成したデータです。
なお、runserver
コマンドを叩いたときにhttp://127.0.0.1:8000/
でサイトが見れますというふうに言われるのですが、このタイミングだとlocalhost
しか受け付けない設定になっているのと、CSSやjsなどフロント周りの静的ファイルを生成していないのでhttp://localhost:8000/
にアクセスしても見た目がくずれている状態です。
一旦Ctrl+C
でサーバーを停止して次に進みます。
※もし違うコマンド(Ctrl+Z
)やターミナル自体を閉じてしまうと、サーバーは起動したままになります。そんなときはlsof
コマンドでポート番号からプロセスを探して、kill
コマンドでプロセスを終了できます。
$ lsof -i :8000
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
python3.6 12685 user 6u IPv4 0x581221ac75463bd3 0t0 TCP localhost:irdmi (LISTEN)
$ kill -9 12685
npmでフロント周りの静的ファイルを生成
ということで、最後にフロントまわりの静的ファイルを生成します。
PinaxではCSSやjsなどのファイルを管理するためにnpmという技術を利用しているので、npmを使って静的ファイルを生成するところまで進めます。流れとしては、
- nodebrew(nodeのバージョン管理ツール)をインストール
- Node.jsとnpm(Node.js製のパッケージマネージャー)をインストール
です。またバージョンとかパッケージマネージャーとかが出てきて辟易とするかもしれませんが、一度入れてしまえば便利な技術です。
先程はPython2とPython3を別々に入れたのでしっかりと扱いませんでしたが、nodeのバージョン管理ツールであるnodebrewのように、Pythonのバージョン管理ツールであるpyenvというものもあります。
では一番最初にインストールしてMacOS全体のパッケージマネージャーであるHomebrewを利用して、nodebrewをインストールします。
$ brew install nodebrew
nodebrewのバージョンを見てみます。
$ nodebrew -v
nodebrew 1.0.0
そして、setup
コマンドで設定周りの指示を受けます。
$ nodebrew setup
Fetching nodebrew...
Installed nodebrew in $HOME/.nodebrew
========================================
Export a path to nodebrew:
export PATH=$HOME/.nodebrew/current/bin:$PATH
========================================
パスを通すように書いてあるので、上記で表示されたコマンドを実行します。
$ export PATH=$HOME/.nodebrew/current/bin:$PATH
nodebrewは複数バージョンのNode.jsを管理するので、インストール→どれを利用するか指定するという流れになります。今回はv9.3.0
を使います。
(安定版のv10.3.0
を試しましたが、pinaxが対応していないようでした。)
$ nodebrew install-binary 9.3.0
インストールされたバージョンを見てみます。
$ nodebrew list
v9.3.0
current: none
まだcurrent: none
なので、どのバージョンも指定されていません。今インストールしたバージョンを指定します。
$ nodebrew use 9.3.0
use v9.3.0
すると、node.jsとnpmが使えるようになります。
$ node -v
v9.3.0
$ npm -v
5.5.1
ようやくWebアプリケーションの方に戻ることができます。最初に今いる同一階層にあるpackage.json
というファイルの定義に従って必要なパッケージをインストールします。
$ npm install
続いて、Pinaxで用意されているcssファイルとjsファイルを生成します。
$ npm run dev
すると、static/dist/
配下に静的ファイルが生成され、先程シャットダウンした開発用サーバーが起動しました。
ここでhttp://localhost:8000/
にアクセスすると、見た目がちゃんとしたトップページが表示されます。
Bootstrap4を使っていて、整っています。
会員登録やログイン・ログアウト、登録情報の変更、退会などもできるので試してみてください。
ちなみに、このnpmの定義ファイルpackage.json
は大まかにnpmでどのようなライブラリを管理するか、そしてどのようなscriptの処理を持つかを司っています。このscriptの部分を見ると、下記のようになっています。
"scripts": {
"clean": "rm -rf static/dist && mkdir -p static/dist/js && mkdir -p static/dist/css && mkdir -p static/dist/images",
"build:js": "browserify -t [ babelify --presets [ env ] ] -t envify -o static/dist/js/site.js static/src/js/index.js",
"build:css": "node-sass static/src/scss/index.scss static/dist/css/app.css",
"copy:images": "cp -r static/src/images/* static/dist/images/ 2>/dev/null || :",
"optimize:js": "uglifyjs static/dist/js/site.js -m -c warnings=false -o static/dist/js/site.js",
"optimize:css": "cssnano static/dist/css/app.css static/dist/css/app.css",
"optimize": "npm run optimize:js && npm run optimize:css",
"watch:test": "onchange static/src/js/**/*.js -- npm run test",
"watch:lint": "onchange static/src/js/**/*.js -- npm run lint",
"watch:js": "watchify -t [ babelify --presets [ env ] ] -t envify static/src/js/index.js -o 'exorcist static/dist/js/site.js.map > static/dist/js/site.js' -dv",
"watch:css": "node-sass static/src/scss/index.scss static/dist/css/app.css --watch -r",
"build": "npm run clean && concurrently \"npm run build:js\" \"npm run build:css\" \"npm run copy:images\" && npm run optimize",
"watch": "npm run clean && npm run copy:images && npm run build:css && concurrently --raw \"npm run watch:lint\" \"npm run watch:js\" \"npm run watch:css\"",
"dev:browser-sync": "browser-sync start --no-open --proxy localhost:8000 --files \"static/dist/js/*.js, static/dist/css/*.css\"",
"dev": "concurrently --raw \"./manage.py runserver\" \"npm run watch\" \"npm run dev:browser-sync\"",
"lint": "eslint static/src/**/**/*.js",
"test": "mocha --recursive --compilers js:babel-register static/src/tests/index.js",
"compile": "NODE_ENV=production npm run clean && concurrently \"npm run copy:images\" \"npm run build:js\" \"npm run build:css\"",
"heroku-postbuild": "npm run compile && npm run optimize"
},
この中にある dev
というのが、npm run dev
というコマンドを叩いたものです。これを見ると、
-
manage.py runserver
: Webサーバーを起動してアプリケーションにローカルでアクセスできるようにする(先程叩いたコマンドです。) -
npm run watch
: scssファイルに変更があったときに、変更を検知してcssファイルを更新する。 -
npm run dev:browser-sync
: 静的ファイルが更新されると、ブラウザをリロードする
という3つのコマンドが内包されているのがわかります。
このあとでIDE(統合開発環境)であるPyCharmを使っていきますが、その時はnpm run watch
を、またVPSにデプロイしたあともWebアプリケーションを動かすのはApacheの役割でmanage.py runserver
は必要ありません。そのためVPS上でもnpm run watch
のみを使うことになります。
次回
とまあコードを一行も書いていませんが、何やらできあがりました。
次回はPython用統合開発環境(IDE)であるPyCharmをセットアップし、Django製Webアプリケーションの開発を効率的に行うための土台を作ります。