GAEではじめてのFlaskアプリをつくる[Progate修了レベル]

Google App Engine(以下、GAE)のスタンダード環境(Standard Environment)でFlaskを用いて簡単なWEBアプリをつくります。

想定レベルは「Progateで一通りPythonはやったけど、まだ実際にアプリを作ったことはないしフレームワークなにそれ」の人です。


...ごめんなさい、若干盛りました。デコレータ がわからない人は先にこのページを読んできてください。...でも書くコードの100%理解していなくても気持ち悪くない、いわゆる「おまじない」が嫌じゃなければ正直デコレータ を理解していなくても大丈夫です。


...あ、httpプロトコルについては簡単に知っていた方がいいですね。「GETメソッド」「クエリ」「絶対パス・相対パス」の意味くらいはわかってからの方がいいと思います。ぐぐればトータルで15分くらいで理解できる内容かと思います。


基本的に公式チュートリアルを日本語で噛み砕いた内容です。

なお、PCはMac/Linuxでpip, python, virtualenvはインストール済み想定です(インストールがまだの場合はこちら)。念のため最新版にアップデートしておきましょう。ただし、今回はGAEのスタンダード環境の制限のため、Pythonについては2.7でないといけません。3.5などをインストールしている場合もこちらを参考に2.7に切り替えておいてください。

あとGoogle Cloud Platformのアカウントは持っているしGoogle Cloud SDKもインストール済みです。

ディレクトリを準備

まずは自分のPC上で今回つくるアプリのディレクトリ(フォルダ)を作成します。
今回は「myapp」というフォルダを作ったことにして話を進めます。(写真は中にいろいろ入ってますが、これは完成系です。今はmyappフォルダをつくってくれればOK)
f:id:simonsnote:20180530194711p:plain:w400

ディレクトリの中身はこんなかんじです。(それぞれのファイルの用意の仕方もこれから解説します。)
※なお、たとえばtemplates/とは「templates」という名前のディレクトリ(フォルダ)のことです。なお、ターミナル(コマンドライン)がわからない方は先にProgateかなんかで学習してきた方がいいと思います。

  • myapp/
    • main.py
    • static/
    • templates/
    • app.yaml
    • appengine_config.py
    • requirements.txt

なお、GAEに限らずFlaskで必要となるのはtemplates/より上の部分です。app.yaml以下はGAE用の設定ファイルです。

appengine_config.pyの作成

以下の内容のpythonファイルをつくってmyappフォルダの直下に置きます。
(テキストエディタにコピペして、「appengine_config.py」という名前で保存すればOK)

from google.appengine.ext import vendor
vendor.add('lib')

requirements.txtの作成

以下の内容のテキストファイルをつくってmyappフォルダの直下に置きます。拡張子は.txtです。

Flask==0.12.2
Werkzeug<0.13.0,>=0.12.0

ここに書いたものがあとでpipコマンドによってlibディレクトリにインストールされるわけです。

今回はFlaskフレームワークを利用します。
FlaskはWerkzeugというWSGI規格のアプリ(これは...そういうもんと思ってください)をつくるためのツールと、Jinja2というテンプレートエンジン(HTML内に動的に変数を埋め込むもの。PHPでいうTwig)を利用します。
▷WSGIがなんなのか気になる方はこちらの記事がわかりやすかったです。

あれJinja2はインストールしなくていいのかと思われたでしょうが、これでJinja2もセットでダウンロードされます。

ここではFlaskとWerkzeugのバージョンを指定するので、なるべく最新の安定版を指定しましょう。
最新版はこちらから確認できます。
Flask · PyPI
Werkzeug · PyPI

Virtualenvをアクティベート

Virtualenvはその名の通り「仮想環境」です。これからWEBアプリに必要な各ライブラリや依存ファイルをダウンロードするのですが、Virtualenvを利用すれば自分のMacをごちゃごちゃにしてしまう心配がありません。

ここからはターミナルを使います。

まずはさきほど作成したmyappフォルダに移動します。
▷Macの場合、フォルダを右クリック→Optionを押していると「"〜〜〜"のパス名をコピー」というメニューが出るので、それをクリックしてペーストすればOKです。ただし、パス名にスペースが含まれているとエラーになります。そういう場合はパスを""(ダブルクォーテーション)で囲えばOKです。

cd myappフォルダのパス

Virtualenvに必要なenv/ディレクトリを自動生成します。

virtualenv env

自動生成したenv/bin/activateに対してsourceコマンドを実行すると、virtualenvがアクティベートされます。(=以降は仮想環境に入ります)

なお、仮想環境を終了するときはdeactivateと入力すればOKです。

source env/bin/activate

ライブラリをダウンロード

Flaskライブラリをpipでダウンロードします。
※pipはversion 6.0.0以上である必要があります。pip --versionで確かめましょう。もしそれ以下ならこちらを参考にアップデートしてください。ちなみにGAEのスタンダード環境では2018/5/29現在、利用可能なPythonのバージョンは2.7となります。Python3を利用したい場合はフレキシブル環境(Flexible Enviroment)を選択する必要があります。それぞれの環境の違いはこちらの公式ガイドをご覧ください。

以下のコマンドを入力します。意味は「libフォルダにrequirements.txt(さっき作ったやつ)に書かれているものを全てインストールする」ということになります。

pip install --target lib --requirement requirements.txt

これでmyappにFlaskとWerkzeugをインストールできました。

app.yamlを作成

app.yamlファイルは、Google App Engineに対してアプリケーションの構成を伝えるファイルです。

以下の内容のテキストファイルをつくり、ファイル名を「app.yaml」にしてmyappフォルダの直下に置きます。

runtime: python27
api_version: 1
threadsafe: true

handlers:
- url: /static
  static_dir: static
- url: /.*
  script: main.app

libraries:
- name: ssl
  version: latest

なお、app.yamlの詳しい書き方はこちらに公式リファレンス(英語)があります。
app.yaml Reference  |  App Engine standard environment for Python  |  Google Cloud


ここまででGoogle App Engineのための設定は終わりです。ここからはFlaskアプリケーションの設計になります。

Flaskアプリケーションの設計

出力するHTMLを用意する

Flaskでは出力するHTML(HTML以外にもXML、XHTMLにも対応しています)templates/ディレクトリに入れておきます。今回は簡単なWEBページを表示するので、HTMLファイルを用意します。

もちろん静的な(普通の)HTMLだけでなく、文中に変数を埋め込んだ動的なHTMLも用意できます。その時に使うのがテンプレートエンジンであるJinja2ですね。
▷ちなみにどうでもいいですが、Jinjaは「神社」です。公式サイトを覗いてみると鳥居までありますよ。

今回は静的なHTMLファイルと、Jinja2で変数を埋め込んだHTMLファイルの2通りを用意します。

静的なHTMLファイル

これはもうそのまんまです。
今回はこんなかんじのHTMLファイルをつくって、toppage.htmlという名前でtemplates/ディレクトリに保存します。

<html>
    <body>
        Welcome to Myapp!!
    </body>
</html>
変数を埋め込むHTMLファイル

Jinja2では{{ }}で囲った部分が変数として扱われます。

今回は受け取ったユーザーの名前を表示するページを作ってみます。

<html>
    <body>
        あなたの名前は{{ name }}ですね。
    </body>
</html>

この{{ name }}に、次のステップで作るmain.py内のPythonコードから値を渡すわけです。作ったファイルの拡張子は普通に.htmlでOKです。showname.htmlという名前でtemplates/ディレクトリに保存しましょう。

main.pyを書く

main.pyはその名の通り、Pythonで書かれたFlaskアプリのメインファイルです。基本的なFlaskアプリの仕組みは、

  1. main.pyが通信リクエスト(httpなど)を受け取る
  2. templates/に格納されているHTMLファイルをレスポンスとして返す

という流れになります。static/フォルダにはCSSやJavascript、画像ファイルなどのHTMLから参照する静的(static)なファイルをいれておきます。


当然ながら実用的なWEBアプリをつくるにはすべてのPythonコードを1ファイルに書いていたら管理しにくすぎるのでファイルは分割しますが、べつにmain.py1ファイルにすべてのコードを書いてもOKです。今回は初めてのFlaskアプリ作成なので、全体の流れを見通すために1ファイルで書くことにしましょう。


以下、main.pyの内容です。テキストエディタで作成しましょう。

文字コードを指定する

コード中に英数字しか書かないなら問題ないのですが、もし日本語を含める場合は文字コードを指定しないとエラーになります。

最初にこのようにコメントの形で書けばOKです。プログラムの1〜2行目にこのようなコメントを書くと例外的にコメントではなく文字コードの指定として扱われます。

# coding: UTF-8
flaskパッケージをimportする

さて、そうしたらまずはflaskのライブラリ(flaskモジュール)を読み込みます。

import flask

flaskモジュールとはすなわちflask.pyのこと...とProgateで習いましたよね。import flaskflask.pyを読み込むはずです。しかしlibフォルダのどこを探してもflask.pyなんていうファイルはありません。

...じゃあどうなっているのかというと、Pythonには「パッケージ」という機能があります。これについては詳しくはまた今度、コードを複数ファイルに分割して書く方法とあわせて説明しますが、要するにここではimport flaskflask/ディレクトリ内すべてを読み込みます。

なので正確にいうとimportしたのはflaskモジュールではなくflaskパッケージです。

インスタンス'app'を作成する

flaskパッケージをimportして最初にやることは、flaskパッケージ内(具体的にはapp.pyで定義されているFlaskクラスのインスタンスを作成することです。

Flaskクラスはアプリケーションそのものを定義するクラスです。よってFlaskクラスのインスタンスはアプリケーションそのものです。

Flaskクラスの引数にはモジュール/パッケージ名を入れます。

今回はmain.py(='main'モジュール)1ファイルで作成するので、こうなりますね。

app = flask.Flask('main')

これはつまり、「appインスタンスは'main'モジュールを参照するFlaskアプリケーションである」ということです。

...おいおい、自分自身のファイル名もわざわざ入力してやらなきゃわかんねえのか?と思いますよね。実はもっといい書き方があります。Pythonには__name__という変数が予約されています。これは自分自身のモジュール/パッケージ名を表します。
▷厳密には場合によるのですが、またこんど説明します。

なので、上のコードはこのように書き換えられます。

app = flask.Flask(__name__)
ルーティングを作成する

appインスタンスを作成したら、あとはFlaskクラスに定義されているメソッドであるrouteを利用してパス(URLのこと)ごとの処理を関数として書いていくだけです。ちょっとイメージわいてきたでしょ?

さて、routeメソッドの内部処理がどうなっているのか見ていくのはprint関数の仕組みを見るのと同じで、つまり「WEBアプリケーションをつくる」という観点からすると不要です。

実用的には、routeメソッドにパスと関数を渡すと、そのパスにアクセスしたときにその関数を実行する」という理解でOKです。
▷厳密には「アクセス」というか「リクエスト」です。一般的にブラウザでWEBサイトにアクセスするということは、サーバーに対してURL(パス)という形のリクエストを送り、そのリクエストに対するレスポンスとして受け取ったHTMLを画面に表示しているわけです。なので一般的なWEBサイトでもバックグラウンドで使う(REST)サーバーでも、仕組みは一緒です。詳しくは「通信プロトコル」とか「httpリクエスト」についてぐぐってもらえれば勉強できます。


さて、具体的にどうやって「パスと関数を渡す」のでしょう。デコレータ を理解していればここは想像がつきますね。
▷デコレータ を理解していなくても実用上は問題ないのですが、理解しておけばなんでこの形になってるかがわかります。デコレータ の解説はこちらからどうぞ。


さて、デコレータ について軽くおさらいします。
関数routeに引数としてパス/mypage関数myfunctionを渡したような挙動の関数を定義したい場合、デコレータ を用いてこう書きます。

@route('/mypage')
def myfunction(なんらかの引数):
    処理

今回routeappのインスタンスメソッドなので、app.routeの形で呼び出します。

なので、ルーティングの形はこうなります。

@app.route(パス)
def 関数名(なんらかの引数):
    処理

あとはこのセットをパスの数だけ用意して、それぞれにパスごとの処理を書けばいいのです。


今回は初めてなので、まずはさっき用意した静的なページtoppage.htmlを出力することにしましょう。
トップページにしたいので、@app.routeの引数は'/'とします。

パス(=リクエスト)が'/'のときの処理を関数として書きます。関数名はなんでもいいです。今回は引数はいらないですね。

templates/に格納しているHTMLを出力するには、flaskパッケージに定義されている関数であるrender_template(ファイル名)を利用します。

@app.route('/')
def toppage():
    return flask.render_template('toppage.html')

これで、「'/'にアクセスされたときはtoppage.htmlを出力する」というコードができました。


...実は、(トップページを表示するだけでいいのであれば)ここまででもうWEBアプリは完成しているのです。コードらしいコードなんて最後の数行だけしか書いてないのに、もうこれで一通りなのです。あとはページやら処理やらを増やしていくだけです。


さて、しかし今回はもうひとつページをつくります。先ほどshowname.htmlをつくりましたね。あれを出力しましょう。

さて、今度はJinja2による埋め込みのある、動的なページです。さっきと同じようにrender_template('showname.html')をやるだけだと、埋め込んだ変数を利用できません。

実はrender_templateメソッドには出力するファイル名以外にも引数を渡せます。

@app.route('/showname')
def showname():
    return flask.render_template('showname.html', name='フラスク太郎')

これでOKです。雰囲気でわかると思いますが、引数としてテンプレート内の変数に値を代入できるのです。render_template('showname.html', name='フラスク太郎', age='50歳', film='ベニスに死す')のようにいくらでも増やせます。

しかしこれでは表示する名前が「フラスク太郎」に固定されてしまって、変数を埋め込んだ意味があまりありません。

ということで、クエリで受け取った名前を出力するようにしてみましょう。
▷「クエリ」とはhttp://exapmle.com/abc?name=taro&age=50のようなリクエストURLの?name=taro&age=50の部分です。このURLの意味は、「パスはhttp://exapmle.com/abcnametaroage50」という意味です。パラメータを複数用意するときは&で接続します。

FlaskではURLやクエリを扱うメソッドが用意されています。

完全なURLはrequest.urlで取得できますし、クエリ文字列はrequest.query_stringで取得できます。

しかしクエリを扱う際に最も便利なのはrequest.argsです。ここにクエリパラメータが辞書型で入っています。たとえばhttp://exapmle.com/abc?name=taro&age=50というリクエストが来た時には、request.args['name'] == 'taro'となります。

これを使って、リクエストのクエリのパラメータ「name」の値をHTMLに埋め込んだ変数{{ name }}に渡しましょう。

@app.route('/showname')
def showname():
    name = flask.request.args['name']
    return flask.render_template('showname.html', name=name)

これでmain.pyは完成です!

完成したmain.py

main.pyはこのようになりました。

# coding: UTF-8
import flask

app = flask.Flask(__name__)


@app.route('/')
def toppage():
    return flask.render_template('toppage.html')

@app.route('/showname')
def showname():
    name = flask.request.args['name']
    return flask.render_template('showname.html', name=name)

ちなみに下のように書いても同じことです。import文の挙動を理解していればわかりますね。(実はこっちの方がメジャーな書き方です)

# coding: UTF-8
from flask import Flask, render_template, request

app = Flask(__name__)


@app.route('/')
def toppage():
    return render_template('toppage.html')

@app.route('/showname')
def showname():
    name = request.args['name']
    return render_template('showname.html', name=name)

staticファイルを用意する

CSS /JavaScriptや画像ファイルなどstatic(静的な)ファイルを用意する場合はstatic/フォルダにいれておきます。

静的ファイルはURLで参照するだけなので別に必ずこのstatic/フォルダにいれなければいけないわけではなく、Google Cloud Storageのような外部サービスを利用しても全く問題ありません。

今回はCSSを用意しましょう。

以下のような内容のCSSファイルを作って、stylesheet.cssという名前でstatic/フォルダ内に保存しましょう。

body{
    background:pink;
}

用意したCSSを読み込むようにHTMLにCSSへのリンクを加えましょう。今回はトップページのみこのCSSを読み込むようにします。

toppage.htmlを以下のようにします。

<html>
    <head>
        <link rel="stylesheet" type="text/css" href="/static/stylesheet.css">
    </head>
    <body>
        Welcome to Myapp!!
    </body>
</html>

app.yamlを作成した際に、こんなふうに設定していました。(抜粋)

handlers:
- url: /static
  static_dir: static
- url: /.*
  script: main.app

これは「URLが'/static'で始まる場合はstatic/フォルダを参照し、それ以外はmain.appに渡す」という指示になっています。

アプリ自体は完成!テストしよう

これでFlaskアプリ自体は完成です!

あとはこのアプリをGoogle App Engineにデプロイする(アップロードして利用可能にする)だけなんですが、その前にちゃんと動くのか手元で試しに動かしてみましょう。

これはGoogle Cloud SDKで簡単にできます。


ここからはターミナルでの作業です。

まずはmyapp/フォルダの直下ルートディレクトリといいます)に移動します。
▷myappフォルダのパスの取得方法を忘れてしまった場合はこちら

cd myappフォルダのパス

そうしたら、以下のコマンドを入力します。

dev_appserver.py app.yaml

これで、自分のPCの8080番ポートで今作ったアプリが動いている状態になりました!
ブラウザで以下のURLにアクセスしましょう。
'localhost'とは自分自身という意味です。

http://localhost:8080/


...ちゃんとこんな画面が表示されましたか?
f:id:simonsnote:20180530195637p:plain:w400

背景がピンク色なら、CSSもしっかり配置できているということですね。

試しにhttp://localhost:8080/static/stylesheet.cssにアクセスしてみると、ちゃんとCSSファイルが表示されます。
f:id:simonsnote:20180530195650p:plain:w400

さて、次は/shownameページをみてみましょう。

http://localhost:8080/showname


こんな画面が表示されましたね?
f:id:simonsnote:20180530195706p:plain:w400

クエリをつけなかったので、名前を表示する部分には'None'が入っています。これを避けるにはif文でパラメータが空の場合の挙動を設定してあげればいいですね。(今回はそこまでやりませんが、このくらいのアレンジはもうできますよね?)

クエリに名前をいれてもう一度アクセスしてみましょう。

http://localhost:8080/showname?name=フラスク太郎


パラメータ'name'の値が変数nameにちゃんと代入されています。
f:id:simonsnote:20180530195721p:plain:w400

ちなみにdev_appserver.py app.yamlの実行中にmyapp内に変更を加えることができます。変更はすぐに反映されます。リアルタイムプレビューとして利用できるので、これは開発に便利ですね!試しにどこかいじってブラウザを更新してみてください。

テスト(localhost:8080への出力)を終了するには、ターミナルでcontrolキーを押しながらcです。

Google App Engineにデプロイ

いよいよGoogle App Engineにデプロイします。これもターミナルからGoogle Cloud SDKでワンコマンドです。

myappのルートディレクトリに移動します。

cd myappフォルダのパス

gcloudコマンドでデプロイします。
'プロジェクトID'の部分にはGCPの「ホーム」画面の左上にある「プロジェクト情報」の中の「プロジェクト ID」に書いてある英数字をそのままコピペします。(というかGoogle Cloud SDKインストールしたときにもうやったはずですよね)

gcloud app deploy --project プロジェクトID

これでデプロイ完了です!
▷デプロイについて詳しくはこちらの公式チュートリアル(英語)をご覧ください。


すでにいまデプロイしたmyappは世界中に公開されています。デフォルトのURLは以下のようになります。

http://プロジェクトID.appspot.com/

もちろん独自ドメインを設定することも可能です。それはまた次回。


ご質問などあれば気軽に下のコメントにお書きください!

Mac/LinuxにPython開発環境一式をインストール

PythonでWEBアプリをつくるには、手元のPCに開発環境を作っておく必要があります。

Pythonでの開発には以下のものが必要です。

  • Homebrew
  • Pyenv
  • Pythonそのもの
  • pip
  • Virtualenv

上から順番にインストールしていきます。
なおMacには標準でPython2.7がインストールされているはずです。が、Pythonの最新版は3.5です(2018/5/29現在)。基本的には最新版をインストールしたらいいと思います。その場合もこのページにしたがってPython3をインストールしなおせばOKです。
※しかしながら、例えばGoogle App Engineのスタンダード環境ではPython3には対応していません。そういう事情があれば2.7でもいいでしょう。まあ既に古くなっているバージョンから覚え始めるのはあまりいい気はしませんが...。Pyhton2と3の違いはこちらの記事がわかりやすかったです。

なお、これからの作業はすべて管理者権限のあるユーザーとしてログインしたうえで、ターミナルにて行います。

Homebrewのインストール

HomebrewはMac用のパッケージマネージャの定番です。パッケージマネージャとは簡単にいうとApp Store的な、各ソフトのインストールやアップデートを一元管理できるプログラムです。インストールしておけば今後もなにかと便利でしょう。

まずはhomebrewが既にインストールされていないか確かめます。

brew -v

command not found」と表示された場合はインストールされていません。以下のコマンドでインストールします。

/usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"

Enterキーの入力を求められたら応じましょう。また、パスワードを求められたらログインしているユーザーのパスワードを入力します。

終わったら、もう一度以下のコマンドを入力してインストールが成功したか確かめます。バージョン番号がでれば成功です。

brew -v

Pyenvのインストール

PythonのインストールにはPyenvが必要です。PyenvはPythonを使う上でめちゃくちゃ便利です。

PyenvはさっきインストールしたHomebrewでインストールします。

brew install pyenv

インストールできたか確かめます。

pyenv -v

インストールできたら、.bash_profileにpyenvを利用できるように設定を追加する必要があります。
.bash_profileとはMac/Linuxのコマンドを定義するファイルです。今回pyenvのコマンドを追加するので、.bash_profileに書き加える必要があります。(.bash_profileについては詳しくはこちらがわかりやすかったです)

これら3つのコマンドを順番に実行します。

echo 'export PYENV_ROOT="$HOME/.pyenv"' >> ~/.bash_profile
echo 'export PATH="$PYENV_ROOT/bin:$PATH"' >> ~/.bash_profile
echo 'eval "$(pyenv init -)"' >> ~/.bash_profile

3つ入力したら、sourceコマンドで今変更した設定を反映します。

source ~/.bash_profile

Pythonのインストール

Pyenvをインストールできたら、それを使ってPythonをインストールします。

以下のコマンドを実行すると、インストール可能なPythonの一覧が表示されます。

pyenv install --list

大量のリストが表示されたと思いますが、これらはすべてPythonのバージョンです。なにかアルファベットがついているのは基本的にデベロッパーズバージョン(早くいえばベータ版)です。上にスクロールしていって3.6.5のような数字だけのものを探しましょう。それが安定版です。

みつけた安定版のうち、いちばん新しいものを以下のようにコマンドに入力します。

pyenv install 3.6.5

インストールされたバージョンは以下のコマンドで確認できます。

pyenv versions

しかしながらこの状態ではまだインストールしただけで、Pythonのデフォルトのバージョンとして選択していません。globalコマンドでデフォルトのPythonのバージョンを切り替えられます。

pyenv global 3.6.5

さて、そうしたら試しにpython --versionでMacが呼び出すPythonのバージョンを確認してみましょう。

python --version

pipのインストール

ここまでで最新のPython自体はインストールできました。しかしこのままではまだPythonでWEBアプリをつくることはできません。もうこういうの一括でやってくれるソフトないんですかね。

pipはPythonでWEBアプリをつくる場合は必須の公式パッケージマネージャです。

このあとインストールするVirtualenvや、PythonでWEBアプリをつくる場合は必須のフレームワークであるDjangoFlaskもpipで簡単にインストールできます。

公式に配布されているget-pip.pyというPythonファイルを実行すればインストールできます。
こちらの公式サイトからブラウザ経由でダウンロードしてもいいですし、以下のcurlコマンドでもダウンロードできます。

curl https://bootstrap.pypa.io/get-pip.py -o get-pip.py

ダウンロードしたら、get-pip.pyファイルを実行します。
▷ブラウザでダウンロードした場合はあらかじめget-pip.pyファイルをユーザーディレクトリ直下に移動しておいてください

python get-pip.py

これでpipをインストールできました。念のため最新版にアップデートのコマンドを実行しておきましょう。

pip install --upgrade pip

Virtualenvのインストール

Virtualenvはその名の通り「仮想環境」です。Flaskなどフレームワークを利用してWEBアプリをつくる際、必要なライブラリや依存ファイルをこのVirtualenvの中に閉じ込めておけるので、PCの中身をごちゃごちゃにしてしまう心配がありません。

インストールはpipを使ってワンコマンドで完了です。

pip install --upgrade virtualenv

バージョンは以下のコマンドで確認できます。

virtualenv --version

virtualenvの詳しい使い方はGAEでFlaskアプリを立ち上げるのページで解説しています。

おわり

これでPythonでの開発の準備ができました。次回はGoogle App EngineでPythonのフレームワークとしてメジャーなFlaskを立ち上げます。

Progateを修了したばかりみたいな人がいきなりフルスタックフレームワーク(DjangoやRuby on Rails)を扱うのはよくないと思います。なにがなんだかわけがわかりません。おまじない祭りになります。Flaskは「マイクロフレームワーク」を自称するように、シンプルですべての挙動を理解しながらWEBアプリを構築できます。そのうちDjangoを使うにしても、フレームワークとはどういうものか、WEBアプリはどういう仕組みで動いているのか、データベースとはなにかということをFlaskで体感してからの方がいいと思います。

Pythonのデコレータの最もシンプルな例(Progate修了レベル)

ProgateでPythonのレッスンを修了したばかりのあなたへ。「Pythonマスターしたぜ!」の気分になってDjangoやらFlaskやら実践編をぐぐってみたところわけのわからない「@(アットマーク)」記法にめまいがしている頃かと存じます。

心配無用、私のことです。この記事で10分で@をマスターしましょう。

@記法の正体

デコレータというらしいです。

Pythonはオブジェクト指向の言語(RubyやSwiftなどもそう)なので、関数もオブジェクトです。

関数がオブジェクトであるとは

つまりこんなこともできるということです。

関数自体を変数に代入
def func(int):
    return int + 1

var = func

print(var(1))

実行結果

2
関数の引数に関数

関数の引数に別の関数を使うこともできます。

def func1(func,text):
    return func + text

def func2(text):
    return text

print( func1(func2('Hello'),' world') )

実行結果

Hello world

引数にとった関数の引数を使いたい

デコレータとは、「関数を引数にとって、新しい関数を返す」関数と考えてもらってOKです。
▷厳密にいうと関数ではなく「callable」というらしいですが、まあ関数と思っていていいでしょう。ちなみに関数はcallableの一種だそう。

さて、関数A(関数B( C )) という例を考えましょう。

関数Bを引数にとるからには、その引数 C 関数Aの中で使いたいですね。

しかしこんな書き方はシンタックスエラーになります。

def func1(func(arg),text):
#実行結果:SyntaxError: invalid syntax

困りましたね。これではfunc1(関数A)にarg(関数Bの引数 C )を渡せません。

これを解決するには、こんな書き方をしなければなりません。

def func1(func,text1):
    def innerfunc(arg):
        def func3(text3):
            return ' [' + text3 + '] ' 
        return func(arg) + text1 + func3(arg) + arg
    return innerfunc

def func2(text2):
    return text2

print( func1(func2,' world')('Hello') )

実行結果

Hello world [Hello] Hello

ちょっとごちゃついてしまいましたが、みてほしいのはfunc2の引数である'Hello'func1の中で自由に使っている点です。

上のサンプルコードの解説

上でなにをやっているのかというと、

まずfunc1に引数をいれる

func1(func2, ' world')

この段階ではfunc2に引数は入れません。(引数をいれた関数=実行結果です。ここでは関数そのものを渡すので、引数は入れない。)
sum([1,2])は数値3であって関数sumではないですね。

すると、これはすなわち関数innerfuncを返します。

そうしたら、返された関数innerfuncに引数をわたせばよいのです。

func1(func2,' world')('Hello')
#func1(func2,' world') == innerfunc なので
#func1(func2,' world')('Hello') == innerfunc('Hello')

そうしたら、あとはfunc1の中のinnerfuncに引数'Hello'を入れた結果が出力されます。

さて、デコレータを使おう

デコレータは、上のコードがあんまりごちゃごちゃしているので簡単にまとめてしまおうというものです。

さっきのコードをデコレータを使って書くとこうなります。
※「wrapper」というのが増えてしまっていますが、これはあとで説明します。

def func1(text1):
    def wrapper(func):
        def innerfunc(arg):
            def func3(text3):
               return ' [' + text3 + '] ' 
            return func(arg) + text1 + func3(arg) + arg
        return innerfunc
    return wrapper


@func1(' world')
def func2(text2):
    return text2

print( func2('Hello') )

実行結果

Hello world [Hello] Hello

つまりfunc2 == デコレータ無しの場合の func1(func2,' world')ということです。

一般化して書くとこうなります。

@func1(引数A)
def func2(引数):

#と書いたとき、

func2(引数B)
#はデコレータがなかった時の
func1(func2(引数B),引数A) 
#を表す

func1の引数(wrapperを使う)

func1関数A)にfunc2関数B)以外の引数を入れる場合(上のケースがそうでしたね)は、func1(func,arg):のような形のままデコレータを使うとシンタックスエラーになってしまいます。

そういうときはwrapperを使います(別に名前はなんでもいいです)。

書き方は上のケースを参考にしてください。func1自体の引数には関数は入れません。関数を引数にとる関数を内部で新たに定義し、ワンクッション置く形になります。

wrapperが要らない場合

func1関数A)の引数にfunc2関数B)しか入れない場合はこの書き方は不要です。その場合はこんな風に書けばOKです。

def func1(func):
    def innerfunc(arg):
        def func3(text3):
           return ' [' + text3 + '] ' 
        return func(arg) + ' world' + func3(arg) + arg
    return innerfunc


@func1
def func2(text2):
    return text2

print( func2('Hello') )

実行結果

Hello world [Hello] Hello

デコレータを使わずに書くとこうなります。

def func1(func):
    def innerfunc(arg):
        def func3(text3):
           return ' [' + text3 + '] ' 
        return func(arg) + ' world' + func3(arg) + arg
    return innerfunc

def func2(text2):
    return text2

print( func1(func2)('Hello') )

まとめ

デコレータがわからないと、フレームワークはすべて呪文になってしまいます。そもそもそういうブラックボックスが嫌だからRuby on Railsを避けてPythonを選んでるんでしょ?(僕のことです)

ちなみにデコレータは複数つけられます。(その場合、実行は下からなので注意)

@func2
@func1
def func3(text):
    return text

ご質問などあれば気軽にコメントにどうぞ!

余談:Flaskでよくみる@app.route('/')

Flaskのルーティングで@app.route('/')みたいのがよくでてきますね。意味を知らなくても使えるしすごい楽なんだけど、これもデコレータですね。

そもそもappについては上の方でこういうコードで作ってると思います。

from flask import Flask

app = Flask(__name__)

または(この違いがわからない人はProgateに戻りましょう)

import flask

app = flask.Flask(__name__)

__name__はProgateでも習った__init__と形が似てますね。こういう人間が作りそうにない形のものはだいたいシステムで決まったものですよね。

__name__にはモジュールの名前が自動的に代入されています。Flask(__name__)つまり引数に__name__をとるFlaskクラスのインスタンスがappです。

Flaskクラスにはメソッドroute(self, rule, **options)が定義されているので、このruleに引数としてパス(URL)を渡すわけですね。

このへんの中身を全部把握しようとすると骨が折れるので不要と思います。ここはこんな理解でOKです↓。

@app.route('パス')
def パスごとの処理

__name__について詳しくはこちらがわかりやすかったです。
azuuun-memorandum.hatenablog.com

DrupalをSSL化 [Apache2, Debian]

SSL化とはhttps化のことです。

https化のメリット

SSL化されていないサイト(http:〜で始まるサイト)への接続は

・暗号化されていない
・証明されていない

暗号化

暗号化されていないとうのは、つまりそのサイトでパスワードその他を入力しようものならぜんぶ抜き取られる可能性があるということです。

訪問者にパスワード入力させるところないし...と思っていても、Drupalである以上管理者としてログインしますね?
放置しとくとサイトごとのっとられる危険があります。

ドメインの証明

ドメインの証明がされていないというのは、たとえばカフェの公共Wi-Fiが悪いやつにハッキングされてるとしますね。そこからあなたのサイトに訪問した人は、あなたのドメインをみているつもりが実際はそのハッカーが用意したページをみることになります。つまり、「このドメイン(simonsnote.comなど)は正しい接続先です!」という証明がないので、誰でもあなたのドメインを名乗って偽装サイトを作れます。

訪問者の安全のためにもサイトのブランド保護のためにも、これはまずいですね。

それに、最近のブラウザではhttp:〜ではじまるサイトへの接続時には「セキュアでない接続」などと表示されます。なんかいやですね。

https化のデメリット

デメリットもあります。

・少しページ読み込みが遅くなる
・ミクストコンテンツの対策
・お金がかかる

少しページ読み込みが遅くなる

httpsでの接続では認証局との通信を毎回行うことになるので、そのぶん遅くなります。でも許容範囲内です。写真を圧縮した方が大きいです。

ミクストコンテンツの対策

ページ内にhttp通信の埋め込み(imgのsrcなど)があると、ブラウザに警告がでてしまいます。

とはいえ、いまのところ、たとえばChromeの場合は開発ツールをみないとその警告はわかりません。
なので一般ユーザー的には大丈夫ですね。

お金がかかる

無料のLet's Encryptもありますが、知識のない場合はしんどいです。

有料のものは16,000円/年くらいですね。わかりやすいし確実なので、失敗したく無い場合はこっちにしましょう。

今回はGeoTrustのクイックSSLプレミアムを利用したので、これで解説します。

このページに設定の仕方が詳しく書いてあるので初心者向きです。


※ちなみにSymantecのSSL証明書(GeoTrust含む)が順次無効化されることになっていますが、上のリンク先のGeoTrustブランドは現在DigiCertが運営しているものなので問題ありません。(昨年シマンテック社のSSL証明書事業がDigiCertに譲渡されました。問題になっているのは譲渡以前のSSL証明書。詳しくは↓)
webtan.impress.co.jp

秘密鍵・CSRの作成

申し込みの前に、まずは秘密鍵と「CSR」というものを作成します。顧客満足度ではなくCertificate Signing Requestの略です。

今回はDebian・Apache2が前提です。CentOSとはやり方が違いますが、Ubuntuなら大丈夫だと思います。

ここからはLinuxサーバーに接続してのコマンドライン操作です。

秘密鍵の作成

あらかじめ、秘密鍵に使うパスフレーズを用意しておいてください。
パスフレーズは安全な場所に保管しましょう。

/usr/binに移動

cd /usr/bin

秘密鍵作成のために擬似乱数を生成、ユーザーフォルダに保存します。

sudo openssl md5 * > /home/ユーザー名/rand.dat

作成した擬似乱数を利用してgenrsaで秘密鍵(秘密鍵ファイル名.pem)を作成します。sha256で暗号化します。

sudo openssl genrsa -rand /home/ユーザー名/rand.dat -des3 2048 sha256 > /home/ユーザー名/秘密鍵ファイル名.pem

パスフレーズをきかれるので、きめておいたパスフレーズを入力 を2回行います。

作成した秘密鍵(/home/ユーザー名/秘密鍵ファイル名.pem)は、ダウンロードして保管しておいても大丈夫です。自分でLinuxサーバーの中を自由に歩けないのであればいまダウンロードしておいた方がのちのトラブルやサーバー移転の際に便利でしょう。ただ、どんな場合でも秘密鍵を聞かれることはないので、くれぐれも誰かに教えないようにしましょう。セキュリティがしっかりしたフォルダにしまっておくべきです。

CSRの作成

/usr/binに移動

cd /usr/bin

さっき作成した秘密鍵をもとにCSRファイルを作成

openssl req -new -key /home/ユーザー名/秘密鍵ファイル名.pem -out /home/ユーザー名/CSRファイル名.pem

するといろいろきかれます。
なお、今回の場合(ドメイン認証といいます)はこれらの情報は公開されないので安心してください。

Country Name (2 letter code) [AU]:
→ JP と入力。

State or Province Name (full name) [Some-State]:
→サイトの所有者の住所がある都道府県を「Saitama」のように入力。

Organization Name (eg, company) [Internet Widgits Pty Ltd]:
→サイトの運営者名を入力。

Organizational Unit Name (eg, section) :
→自分で判断できる好きな名前を入力。(同じ申請者が複数の証明書を申請する場合などに、それぞれの証明書の識別に利用されます)

Common Name (eg, YOUR name) :
→証明書を申請するサイトのドメインを入力(例:https://www.simonsnote.comなら、www.simonsnote.com)


この後もいくつかきかれますが、あとはぜんぶなにも入力しないでエンターを押してしまってOKです。

そうしたらCSRファイル(/home/ユーザー名/CSRファイル名.pem)ができたので、ダウンロードします。
Google Compute EngineのSSH画面なら右上のメニューからダウンロードできます。

最初に作成した擬似乱数はもういらないので、削除してしまいます。

rm /home/ユーザー名/rand.dat

CSRファイルも、サーバーに置いておく必要はありません。サーバー上の安全なフォルダ(パーミッション400)で保存してもいいですし、サーバーからは削除してしまってもOKです。(その場合自分のPC上などどこかで保管してください)

サーバーから削除する場合は、以下のコマンドでOK。

rm /home/ユーザー名/CSRファイル名.pem

CSRの提出と、SSL証明書、中間CA証明書の受け取り

ここまでできたら、いよいよ証明書を購入です。

受け取る証明書は「サーバー証明書(SSL証明書)」と「中間CA証明書」の2つです。この2つがSSL化には必要です。

ここから買うと半額になります。
ジオトラストSSLサーバー証明書

何種類かあるかもしれませんが、一番安いもので大丈夫です。

ちょっとややこしいですが、今回は

KDDIウェブコミュニケーションズからクーポンの購入 → 購入したクーポンでジオトラストからSSL証明書を購入

の2段階になります。

申し込んだら1〜2日でKDDIウェブコミュニケーションズよりクーポンコードの書かれたメールが届きます。

メールが届いたら以下の手順に進みます。

まずは、今回はドメイン認証(DV)になるので、SSL証明書を申し込むドメインでメールを受け取ることでドメインの所有を確認する必要があります。

認証メールを受け取るメールアドレスは決まっているので、あらかじめ用意しておきましょう。次のうちのどれかひとつでOKです。

admin@〜〜〜
administrator@〜〜〜
hostmaster@〜〜〜
webmaster@〜〜〜
postmaster@〜〜〜

認証メール受信用のメールアドレスを用意したら、このページに申し込みの手順が説明されていますので、みながら申し込みに進みます。
ジオトラスト ストアフロントご利用方法 (PDF)

まず「1. ユーザ登録」をすませたら、今回は「2.見積取得について」は関係ないのでスキップ。「3.ジオトラスト ストアフロントご利用方法(ドメイン認証の証明書)」をみながら申し込みを済ませてください。

申し込みが完了したら、今回はドメイン認証(DV)なので、すぐにSSL証明書(サーバー証明書)と中間CA証明書がさきほど作成したメールアドレスに届くはずです。

サーバ証明書と中間CA証明書のアップロード

まずは、メールで受け取ったサーバー証明書と中間CA証明書をこのページを参考にコピペしてそれぞれテキストファイルを作ります。

それぞれテキストファイルを作ったら、

サーバー証明書ファイル名.pem
中間CA証明書ファイル名.pem

というようなファイル形式にします(拡張子がpemならなんでもいい)。

そうしたら、アップロードの前に、サーバー上で証明書をいれておくフォルダを作ります。

/usr/binに移動

cd /usr/bin

証明書用の専用ディレクトリを/usr/binにつくる(名前はsslfilesでなくてもなんでもOK)

sudo mkdir -m 700 sslfiles

その中にcertとprivateフォルダをつくります。
certは公開フォルダで、privateは非公開フォルダです。

certフォルダを作成

sudo mkdir -m 700 /usr/bin/sslfiles/cert

privateフォルダを作成

sudo mkdir -m 700 /usr/bin/sslfiles/private

そうしたら、つくったフォルダにサーバー証明書と中間CA証明書をアップロードします。

今回は、まずは
/home/ユーザー名
にアップロードしたとします。

サーバー証明書をcertフォルダに移動

sudo mv /home/ユーザー名/サーバー証明書ファイル名.pem /usr/bin/sslfiles/cert

中間CA証明書をcertフォルダに移動

sudo mv /home/ユーザー名/中間CA証明書ファイル名.pem /usr/bin/sslfiles/cert

それに、最初につくった秘密鍵ファイルもprivateフォルダに移動します。

sudo mv /home/ユーザー名/秘密鍵ファイル名.pem /usr/bin/sslfiles/private

ここまでできたら、パーミッション(アクセス権)を適切に設定しておきます。


秘密鍵ファイルを入れたprivateフォルダは、パーミッション400(管理者のみ読み込み可・書き込み不可)に設定します。

sudo chmod 400 /usr/bin/sslfiles/private

サーバー証明書と中間CA証明書を入れたcertフォルダは、パーミッション444(誰でも読み込み可・書き込み不可)に設定します。

sudo chmod 444 /usr/bin/sslfiles/cert

最後に、sslfilesフォルダをパーミッション444(誰でも読み込み可・書き込み不可)に設定します。

sudo chmod 444 /usr/bin/sslfiles

Apache設定ファイルの書き換え

以上でSSL証明書は完全に準備でき、サイトはhttpsで接続することが準備はできています。

しかしまだApacheによってhttpsでの接続が許可されていないので、設定ファイルを書き直してhttps接続を許可する必要があります。

今回はDebian・Ubuntu想定です。CentOSだと設定ファイルの場所や形式が異なります。

Apache設定ファイルを作成

/etc/apache2/sites-available/default-ssl.confに見本のファイルがあるので、ダウンロードしてみてみてください。

PC上で新しいテキストファイルを作成→アップロードという流れです。

まずは以下の内容のテキストファイルを作ります。(www.simonsnote.comを自分のドメイン名に置き換えてください)

<VirtualHost *:80>
    ServerName www.simonsnote.com
    Redirect "/" "https://www.simonsnote.com/"
</VirtualHost>
<VirtualHost *:443>
    ServerAdmin webmaster@localhost
    DocumentRoot /var/www/html
    ServerName www.simonsnote.com

    SSLEngine on

    SSLCertificateFile /usr/bin/sslfiles/cert/サーバー証明書ファイル名.pem
    SSLCertificateKeyFile /usr/bin/sslfiles/private/秘密鍵ファイル名.pem
    SSLCACertificateFile /usr/bin/sslfiles/cert/中間CA証明書ファイル名.pem
</VirtualHost>

このあともしうまくいかなかったら/etc/apache2/sites-available/default-ssl.confの見本のファイルをダウンロードして足りない場所を探して、このファイルをなおしてみてください。

いまつくったテキストファイルの名前を「myssl.conf」にします(mysslの部分はなんでもよい)

アップロードしたファイルをApacheの設定フォルダに移動します。

sudo mv -i /home/ユーザー名/myssl.conf /etc/apache2/sites-available

設定ファイルを有効化します。

sudo a2ensite myssl.conf

Apacheのsslモジュールを有効化します。

sudo a2enmod ssl

再起動が必要みたいなことをいわれましたね?
Apacheを再起動すれば設定が反映されます。

sudo /etc/init.d/apache2 restart

パスフレーズを求められるので、最初に設定したパスフレーズを入力します。


これでサイトに接続すると...https:〜〜でサイトにつながりましたか?

今回はApacheの設定ファイルでリダイレクトを設定していますので、http:〜で接続しようとしても自動的にhttps:〜〜にリダイレクトされるはずです。.htaccessでの設定よりもこちらの方が正統派の設定です。

さて、無事SSL化が完了したら、これまでのhttp:〜〜で張り巡らしているリンクを張り替える作業が待っています。(まあリダイレクトされるので、すぐに困るわけではないですが。でも一時的にでもhttp:を経由するということはセキュリティリスクになり得ますし、場合によっては訪問者のブラウザが警告を出す可能性もあります。)

独自ドメイン取得時の注意点・ドメイン名の決め方

あなたは今、世界でたったひとつの自分だけの独自ドメインを手に入れようとしていますね?

独自ドメイン導入のメリットを云々しているブログはその辺に無限に転がっているので割愛しますが、ひとつ言わせてほしいのは、独自ドメインは本当に取った方がいいよということ。

僕はいまnoshift.workというサイトを運営して毎月数十万円の収益を出しているのですが、このサイトはもともとはてなブログで始めたサイトです(今は違いますが)。もし独自ドメインを取得していなかったら...この毎月数十万円を生み出す資産ははてなブログのSEO資源として利用され、完全にぼくのものにはなっていません。Googleが自分のドメインをブランドとして評価してくれている状態は最強です。

一番まずいと思うのは、ブログ名が「〜〜.com」みたいな名前なのに実際のドメインが「〜〜〜.hatenablog.com」みたいになってるやつ。これは一番やめたほうがいい。

だって、たとえば仮に自分のサイトを気に入ってくれて、また訪れようと思ってくれた人が「simonsnote.com(という名前のサイト)にアクセスしよう!」と思ってブラウザの検索バーに「simonsnote.com」といれるじゃないですか。独自ドメイン取ってなかったら、存在しない「simonsnote.com(ドメイン)」に誘導されてたどり着けず、おしまいですよ。

正直、今の時代、あらゆるブランド名はドメインを取れるかどうかで決めた方がいいと思います。「simonsnote.com」ってブランドで「simonsnote.com」のドメインとってないのは論外として、たとえば「Orange Days」というブランド名を立ち上げるなら「orangedays.com」は絶対取った方がいい。特にWebサイトやWebサービスなら必須。

ということで、(前置きが長くなってしまいましたが)新しくドメインを取得する・Webサイト/ブログのネーミングについて、あわせてポイントなどまとめます。

ドメインの取得方法はこの記事の最後の方法が多分一番お得です。

ドットコム(〜〜.com)を取りなさい

いまの時代、〜〜.comの部分(トップレベルドメインといいます)はめちゃくちゃ種類があります。

たとえば

〜〜.com
〜〜.net
〜〜.jp
〜〜.org

みたいな基本的なものから

〜〜.work
〜〜.tokyo
〜〜.creditcard

みたいなものまで、本当にたくさんある。基本的にドメインの価格はこのトップレベルドメインごとに決まってます。
たとえば〜〜.comなら1400円/年くらい、〜〜.workならなんと初年度1円とか。

目移りすると思うし値段もちょっと高いけど、まずは〜〜.comを取りなさい!

理由は、〜〜.comが最も資産価値が高いから。

この記事の最後でドメインの取得方法を説明するのでその時にいろいろなワードで空きドメイン検索することになると思いますが、素敵なワードの.comドメインは基本的にもう取られてます。たとえば「coffee.com」とかいまから取れると思いますか?

逆に言えば、「coffee.financial」なら取れるかもしれません(試してませんが)

でもそれって、たとえばあなたが「coffee」ってブランドを立ち上げてこれから大きくしようと思っているならですよ(思っていないならいいですが)、将来的に「coffee.com」が欲しくなるわけですよ。

だって、「coffee」ってブランドの公式ウェブサイトを探している人がいたとします。「coffee.com」と「coffee.financial」がありました。彼はどっちが本物の「coffee」のウェブサイトだと思うでしょう?

そのとき運良く「coffee.com」を買えればいいですよ。ドメインは世界にひとつなので、「coffee.com」みたいな短い.comドメイン(シングルワードドメインといいます)はピカソの美術品と同じようなものなんです。

いま話題になっている「france.com」はWeb黎明期に個人が取得して今も所有しているドメインで、フランス政府が手に入れようと必死になってますね。
gigazine.net

そう。あなたが.comドメインを取得できるか考えずにブランド名/サイト名を決めてしまった場合、あとで大変なんです。

ちなみにぼくは「noshift.work」というドメインを取得後、あとから「noshift.com」を30万円で取得しました。結局欲しくなるから。.com。

ドメインをブランド名の基準にしなさい

これは特にWeb系のブランド名をつけるなら必須です。

たとえば「My Coffee Stand」という名前のサイトをつくったとして、そのサイトのドメインが「mycoffeestand.〜〜」でないというのは非常にユーザーを混乱させます。なんなら「このサイト本物か?」と思わせます。

なので、もしどうしても.comドメインが取れなくても、他のトップレベルドメイン(.netなど)は取得できる名前にしましょう。まあこの場合は上に書いた通りサイトが大きくなったら困ると思いますが...

.comを取れない場合はなるべく「〜〜.net」「〜〜.jp」「〜〜.org」みたいな一般トップレベルドメインと呼ばれるものを取りましょう。

グルメ情報のサイトなのに「gourmet.creditcard」みたいなドメインにしてはいけない理由がわからない人はいないと思いますが、もし「〜〜.creditcard」「〜〜.school」のようなサイトの内容を表すドメインにする場合は、ドメイン名まで含めたブランディングをすべきです。

たとえばぼくの運営する「noshift.work」もそうですね。仮に「noshift」や「noshift work」でブランディングした場合、ユーザーはどんなドメインにアクセスしていいかわかりません。

...とはいえ、これまでnoshift.workを運営してユーザーの方からいろいろフィードバックをもらっているのですが、「noshift.work」という名称はなかなか認知してもらいにくいです...。

そもそも「.work」を.comみたいな類の部分だと認識されていないのでしょう。「なんでそこにドットがあるの?」みたいなかんじです。
やはり一般ユーザーの認知という観点からも、「.com」がベスト、次に「.jp」「.net」というかんじでしょうか。「.info」はスパムっぽい雰囲気があるのでおすすめしません。

ちなみにLINEやPaymoのドメインは「line.me」「paymo.life」です。

ブランド名のネーミングのポイント

さて、ここまでの話で「なるべく.comを取得できるブランド名にしよう」ということになりましたが、ここでこんなこと言って申し訳ないのですが、素敵なワードで.comを取得するのは簡単ではありません

あなたが1億円出せるのならシングルワードドメインでもいいかもしれませんが、普通は次のうちのどちらか、もしくは組み合わせで「ユニークな文字列」を考え出す必要があります。

・2〜3単語を組み合わせる
→3単語だとちょっと長いかも。
例)
DuckDuckGo (duckduckgo.com)
Sound Cloud (soundcloud.com)
JSFiddle (jsfiddle.net)

・まったくユニークな単語、もしくは既存の単語の一部をいじる
→規模の大きいサイト(サイトの内容をユーザーがみんな知っている)を目指すならこっちがいいですね。2音節以内で語呂がいいものを。
例)
Google (google.com)
Qiita (qiita.com)
DMM.com(dmm.com)
freee(freee.co.jp)

日本語ドメインはやめなさい

日本語ドメインはのちに自分でサーバーを立てる際などエンコードが必要になったり、またメッセージアプリでURLをシェアする際にURLと認識されず自動でリンクが付かないなど不便なことばかり。

よほどでないかぎり日本語ドメインはやめましょう。「りんご.com」より「ringo.com」の方が絶対いいです。「〜〜.みんな」みたいな日本語トップレベルドメインは論外。

独自ドメインの取得方法

さてここにきてようやく具体的な独自ドメインの取得方法です。お名前.comとかXdomainとかムームードメインとかいろいろありますが、正直そんなものはどこでもいいです。値段はだいたい一緒です。品質も特に変わりません。

強いていえばお名前.comがシェアが大きい分、ネット上にいろいろトラブルシューティングがあるので楽かな?

さて、大事なのは、いかに安く買うか。どこで買うかを考えるよりも、セルフバックを受け取りましょう。

そう、アフィリエイトです。ブロガーなら登録している方も多いと思いますが、A8.netからお名前.comのセルフバックを受け取れます。

会員登録

「お名前.com」でプログラム検索

「セルフバック」をクリック

でお名前.comのサイトに飛ぶので、あとは普通にドメインを買えばOK。1ドメインにつき100~数百円くらい戻ってきます。


ブログをやるならアフィリエイトは必須(AdSenseはサイトの見た目が悪くなるし収益率が低いのでぼくは導入していません)なので、この機会に登録しちゃいましょう。
ちなみに上のリンクからA8.netに登録してくれるとぼくに500円が入ります。ありがとうございます。これです↓あなたもやってみましょう。
support.a8.net

Drupalコアアップデートを手動で[Debian]

環境はGoogle Compute EngineのVMインスタンス、LAMPスタック(Debian 9, Apache 2.4, MySQL 5.7, PHP 7.0)です。Drupal 8.3.7から8.5.1にアップデートしました。

先日やばいセキュリティアップデートのあったDrupal。

WordPressみたいにボタンでぽちっとコアアップデートできたらいいのですが、Drupalの場合初心者には敷居が高いですよね。
www.drupal.org

公式の案内をみると、将来的にはGUIでのアップデートを準備しているものの、現時点ではComposerか手動でサーバー内のファイルを直接いじるしかありません。
www.drupal.org

Composerでのアップデートは初心者にはなにかと敷居が高く、手動でのアップデートをしました。

作業を始める前に、Drupalに管理アカウントでログインしていることを確認してください。

1. バックアップをとる

必須の作業ではないですが、やらないでアップデートしてどこかでミスした場合は自己責任で青ざめてください。

サイトの設定をエクスポート(Drupal管理画面より)

Drupal管理画面の
環境設定 > 設定の同期 > エクスポート
からtarファイルをダウンロードしておきます。

ここまでは簡単。

サイトのキャッシュをクリア

Drupal管理画面の
環境設定 > パフォーマンス
より、「すべてのキャッシュをクリアー」しておきます。

これで余分なキャッシュを一緒にバックアップしてしまわずにすみます。

サイトのディレクトリをtar.gzでバックアップ

ここからサーバーにアクセスします。

Drupalをインストールしているディレクトリをまるごとバックアップしておきましょう。
だいたいは /var/www/html に入っているかと思いますので、ここをまるごとバックアップします。

まずはインストールディレクトリ(html)の親ディレクトリに移動

cd /var/www

ディレクトリ「html」をまるごとtar.gzファイルにアーカイブします。

sudo tar -czvf htmlbackup.tar.gz html

そうしたらいまつくったアーカイブファイルを、どこでもいいのですがとりあえず自分のユーザーフォルダにいれておきます。

sudo mv -i htmlbackup.tar.gz /home/ユーザー名

念のためアクセス権を400(管理者読み込みのみ)にしておきます。

sudo chmod 400 /home/ユーザー名/htmlbackup.tar.gz

これでバックアップはOK。なにかあったらとりあえずいまつくったアーカイブファイルをダウンロードしてしまえばいいのです。

2. サイトをメンテナンスモードに

ふたたびDrupalサイトの管理画面での操作。
環境設定 > メンテナンスモード
から「サイトをメンテナンスモードにする」にチェックをいれて「設定を保存」をクリック。

これで、一般の訪問者はサイトの普段のページにアクセスできなくなりました。

3. 手動で設定したファイルをバックアップ

インストールディレクトリ(/var/www/html)内の設定ファイル(.htaccessやsettings.phpなど)を手動で設定している場合は、ダウンロードしておきます。

SSLの設定などApacheの設定ファイルは別の場所にあるのでそのままで大丈夫です。

僕と同じようにGoogle Compute EngineのVMインスタンスなら、SSH画面の右上のメニューの「ダウンロード」から、
/var/www/html/sites/default/settings.php

/var/www/html/.htaccess
をダウンロードしておけば大丈夫です。

4.「core」「vendor」ディレクトリとトップレベルディレクトリ内のファイルを削除

続いて、インストールディレクトリ(/var/www/html)直下のファイルたちと「core」と「vendor」ディレクトリをぜんぶ削除します。なんか不安ですが、大丈夫。

インストールディレクトリ(html)に移動

cd /var/www/html

直下のディレクトリたちとファイルたちの存在を確認します。

ls -la

「core」と「vendor」ディレクトリを削除

sudo rm -rf core vendor

直下のファイルを削除

sudo rm -f *.* .*

5.deault.settings.phpに変更がある場合(リリースノートで確認)

インストールするコアのバージョンのページでリリースノートを確認します。

8.5.1ならこちら。
www.drupal.org

もしリリースノートに「deault.settings.phpに変更があるよ!」と言われた場合は追加の作業が必要。今回は必要なかったので、ここは解説しません。

必要なこちらのページの 6. に説明が載ってます。
www.drupal.org

6.新しいコアのダウンロード

さて、いよいよ本題です。新しいバージョンのコアをダウンロードします。

インストールディレクトリ(html)に移動

cd /var/www/html

drupal-8.5.1.tar.gzをダウンロード。バージョンによってここは変えてください。

sudo wget https://www.drupal.org/files/projects/drupal-8.5.1.tar.gz

ダウンロードしたtar.gzファイルをその場に展開。

sudo tar -zxvf drupal-8.5.1.tar.gz

作成された「drupal-8.5.1」ディレクトリの中身を、インストールディレクトリ(html)直下にコピー

sudo cp -rip drupal-8.5.1/* /var/www/html

7.手動でバックアップしたファイルを戻す

3.でバックアップした設定ファイルを戻します。
Google Compute EngineのVMインスタンスの場合は、SSH画面の右上のメニューの「アップロード」から、さきほどダウンロードしたファイルをアップロード。

.htaccessファイルはダウンロードした時にファイル名が変更されている可能性があるので、あらかじめ「htaccess.txt」というファイル名に変更してからアップロードします。

今回は
/home/ユーザー名
にアップロードしたとします。

そうしたら、

インストールディレクトリ(html)に移動

cd /var/www/html

アップロードしたsettings.phpファイルを元の場所( /var/www/html/sites/default)へ

sudo mv -i /home/ユーザー名/settings.php /var/www/html/sites/default


アップロードしたhtaccess.txtファイルを、ファイル名を元にもどしつつ元の場所( /var/www/html直下)へ

sudo mv -i /home/ユーザー名/htaccess.txt .htaccess

8.アップデートの実行

ついにアップデートです。この作業はコマンドラインでなく、普通のブラウザで自分のDrupalサイトにアクセスして行います。

まず、Drupalに管理アカウントでログインしていることを確認します。
そうしたらそのブラウザで

サイト名/update.php

にアクセスします。

アップデート画面に入り、いろいろきかれるのですべてOKします。

これでうまくいけばアップデート成功です。

9.ステータスレポートの確認

Drupal管理画面の
レポート > サイトの状態
をチェックしましょう。

エラーがなければ成功です。

10.ファイルの残骸を削除

最後に
先ほどダウンロードしたファイルの残骸を削除します。

インストールディレクトリ(html)に移動

cd /var/www/html

ダウンロードしたアーカイブファイルを削除

sudo rm drupal-8.5.1.tar.gz

アーカイブを展開したフォルダを削除

sudo rm -rf drupal-8.5.1/

11.メンテナンスモードを解除

すべて終わったら、もう一度「キャッシュをクリアー」してからメンテナンスモードを解除しましょう。


たぶんうまくできたはず?

iPhoneの着信音「オープニング」がOwl City作曲と判明

みなさんおなじみiPhoneの着信音「オープニング」


たららったったったったったった、たったたた♫


を無限に繰り返すアレです。(わかるよね?笑)

この曲がなんと、あのOwl City作曲(らしい)ということが判明しました。

続きを読む

Swift4 任意の場所の外部ファイルの読み込み

Swift4になってCocoa app(mac app)で外部ファイル(txt)の読み込みができず、Swift/Xcodeの頻繁な仕様変更のせいか解決策が見つからずなかなかに苦労しました。

結局、ファイル選択ダイアログを実装することで解決しました。

f:id:simonsnote:20171012202927j:plain

続きを読む

"ZENO-TEAL"の細かい部分のカスタマイズ

f:id:simonsnote:20170724154528p:plain
ZENO-TEALをカスタマイズして当ブログみたいなデザインにする方法をシリーズで紹介してきましたが、最後に細々とした部分をまとめます。

続きを読む

【はてなブログ】フッターに他サイトへのバナーなどを表示

f:id:simonsnote:20170722095557p:plain


今回は上の写真のようなフッタを作ります。(リンク1だけデカイですが、ここだけ見本のコードをいれてるからです。簡単に調整できます。)


シリーズで書いてますが、特に今回はこの記事単体でみてもらっても何の問題もありません。
www.simonsnote.com

続きを読む

【はてなブログ】ページ最上部にメニューバーを設置する(トップページへのリンク、検索ボックス、カテゴリメニューを並べる)

f:id:simonsnote:20170722152215p:plain


この記事はシリーズで書いていますが、今回は特にZENO-TEALに限らずはてなブログで共通して応用できます。
www.simonsnote.com


今回は上の写真のようにページ最上部にメニューバーを出します。

続きを読む