07032013 Python
perlでいうところのPerl::Tidyみたいなものかな。
自分の開発環境ではflymakeはしらせているので、autopep8は必要ないけど、他のヒトのpythonスクリプトを取り込む時には一回かけておくとflymakeに警告されないようになるのでなかなかいいかもしれない。
07032013 Python
perlでいうところのPerl::Tidyみたいなものかな。
自分の開発環境ではflymakeはしらせているので、autopep8は必要ないけど、他のヒトのpythonスクリプトを取り込む時には一回かけておくとflymakeに警告されないようになるのでなかなかいいかもしれない。
06032013 Sass
Sass関連のチュートリアルで、ここ一年の間に更新されたものを探してみた。
にはお目当てのものはほとんどなかったなぁ。
タイトルの通り、VCard を作りながらSassとCompassの作業を学ぶという内容。ワイヤーフレームを使ってデザインしているので、こっち方面が素人すぎる僕には楽しめる内容だった。
socialsectionのところの
text-indent: 100%; whitewhite-space: nowrap; overflow: hidden;
ってなんじゃろかと思ったら[CSS]画像置換「-9999px」のパフォーマンスを改善した新しいテクニックなのね。
レスポンシブ・ウェブデザインのためのグリッドシステムを作ってみようっていう内容。可変グリッドとVertical Rhythmを実装していく。
グリッドシステムは出来合いのを使うことが多いけど、どういう感じで実装されているのかを知っておけば弄りたいときに都合がいいかなと思う。
それからVertical Rhythmはこのサイトがわかりやすかった
スクリーンキャストだけど、時間がかかりそうなので見てない。週末用にストックしておく。
05032013 Sass
Compassのリファレンスにひと通り目を通して、Blueprintのグリッドサンプルを試したので、他のフレームワークというか最近のSass界隈の情報も仕入れたくなったのでググった。
日本語の情報はあまりないね。
酒にちなんだ名前は素敵。
A simple and lightweight mixin library for Sass.と銘打っているようにmixin詰め合わせた感じで、フレームワーク的にCompassに近い。
Bourbon上に構築されたBourbon Neatっていうグリッドフレームワークもあるが、これも働きたくないものは酒を飲めと暗示されているようで素敵感が漂っている。
sofに投稿されそうな質問(で、建設的じゃないという理由で速攻クローズされる)だが。
bourbon派の意見としては、bourbonは分かりやすいらしい。
確かにドキュメントはbourbonのほうが読みやすかった。
Rubyの知識がないとコンパイル時になにやっているのかわからんという指摘もされてた。
一方でCompass派の意見として
CompassはBourbonのスーパーセットみたいなもんだからサブセットなんて必要ないじゃん、存在域がわからん(意訳)
みたいなのもあった。
結論は好きな方使え
Centurionはresponsive web frameworkだ。Docsをみると、んーbootstrapみたいにでかいフレームワーク目指してんのかなぁと思ったが、Hacker newsでも似たような事言われてた(bootstrappyってw)
僕だったらbootstrap-sassを使うな。
bootstrapの対抗だったらFoundationのほうが有名な気がするが、最近バージョンが上がってモバイルファーストになったらしいがよくわからん。
そもそも、フレームワーク臭がいやだなーってことでbootstapの代わりになるようなものを探し始めたのに、フレームワークの比較に収斂しつつあるなんてダメダメだ。
とはいえFoundation4は面白そうなのでそのうち触ってみようっと。
検索してたら見つけた
04032013 Sass
デザイン力とかCSS力が足りないので今年はそこら辺を強化しようとおもっているんだが、CSS拡張メタ言語のいいところは、先人の知恵をライブラリとして取り込んでコモディティ化できることかなと思っている。
既にhail2u.netでも書かれていた
様々なところで公開されているCSSのエッセンスを取り込んだ自分なりのCSS製作環境を構築するというような利用の仕方もできる。つまりはこれこそが必要とされていたスタイルシート言語ということなのではないか。Sass、そしてSassy CSS (SCSS)
Stylus(そしてnib)は構文が好みなんだけど、ユーザーの層が薄いのでとりあえずはSassに入門してみることにした。
Rubyはrbenvで入れてあるので
$ gem update --system $ gem install sass $ gem install compass
でok
ちょっと前にズルいStylus書いててStylusの構文というかそういったあたりのmix-inとかは理解しているので、構文はチュートリアルをざっと読めば理解できた。大体似たような構文だけどsigilがperl風味。
StylusがpythonっぽいとするならLESSとかSass(Scss)はperlとかrubyっぽい。そう考えるとsassはインデントでネストを表現するperlみたいな印象を受けるのでちょっと気持ち悪いし、Stylusのほうがスッキリしていて綺麗に見えるのは納得できる。だったらsassじゃなくてscssで書いたほうがいいかなぁとも思う。
次に、CSS Preprocessor Advent Calendar 2012を読めばよい。これでかなり理解が深まるが、特にOOCSSとSassは構造化の観点からCSSを考える上で非常に参考になる。
cssはクラスベースというよりはプロトタイプベースの継承って考えたほうがしっくりくるかもしれんなぁと思った。spineのextendとincludeと似たような感じだしねー。
あとは次のスライドを読めばいいですね。
M-x list-packagesからscss-modeをインストールする。
これはデフォルトで保存時にコンパイルが走ってうざいのと、インデントが4文字スペースなのでscss-mode.elを使うの通りに設定を変更しておく。
ちなみにファイルを開くとflymake関連エラーが出るけどそれは直してない。
04032013 drum'n'bass
Unquoteから始まりUpbeatsで終わる。
Hide Your Tears Because We Are In Heaven / Unquote Last Night / Kantyze No Ballast / Dan Habarnam Hide U / Kosheen Cosmic Rain / Pluton & Skyer Block Breaker / Krakota The Lighter / DJ SS Heaven (NuTone Remix) / Emeli Sande Fibreglass / Logistics Slice Of Nature / Utah Jazz Beneath The Mask (12"Cut) / Makai Enemies Of The State / Gridlok Saligia (feat. Kemo) / Enei Protocol (Digital Bonus Track) / Spinline Thinking Cap (Feat. Georgie) / The Upbeats
03032013 Python Flask SQLAlchemy
まずはreStructuredTextをHTMLにコンバートするためにdocutilsをインストールします。
pip install docutils
modelを修正してreStructuredTextをHTMLにコンバートするメソッドを追加します。
from sqlalchemy import Column, Integer, String, Text, DateTime from flaski.database import Base from datetime import datetime from docutils.core import publish_parts overrides = {'doctitle_xform': 0, 'initial_header_level': 2} class WikiContent(Base): __tablename__ = 'wikicontents' id = Column(Integer, primary_key=True) title = Column(String(128), unique=True) body = Column(Text) date = Column(DateTime, default=datetime.now()) def __init__(self, title=None, body=None, date=None): self.title = title self.body = body self.date = date def __repr__(self): return '<Title %r>' % (self.title) @property def html(self): parts = publish_parts(source=self.body, writer_name="html", settings_overrides=overrides ) return parts['html_body']
@propertyデコレータを使うことでcontent.html()とメソッド呼び出しではなくcontent.htmlとプロバティとしてアクセスできるようになります。setting_overridesしているのはタイトルをh1要素にしているので、トップレベルのヘッダーをh2から始めたいからです。
それからpostした時の戻り値もhtmlにコンバートしたものにします。
@app.route("/<title>", methods=["POST"]) def post_content(title=None): ...略... return content.html
httpieでちょっとテストしてみます
$ http --form POST http://localhost:5000/rsttest body="rst **strong** and *italic*" HTTP/1.0 200 OK Content-Type: text/html; charset=utf-8 Content-Length: 85 Server: Werkzeug/0.8.3 Python/2.7.3 Date: Sun, 03 Mar 2013 06:29:59 GMT <div class="document"> <p>rst <strong>strong</strong> and <em>italic</em></p> </div>
正しく変換されています。
ブラウザでアクセスした場合にもきちんとHTMLが表示されるようにJinja2テンプレートを修正します。
show_content.html
{% extends "layout.html" %} {% block body %} <h1>{{content.title}}</h1> <div>{{content.html|safe}}</div> <p>{{content.date}}</p> {% endblock %}
content.bodyをhtmlに変更するだけですが、そのままだとHTMLタグがエスケープされてしまうのでsafeフィルターを付ける必要があります。

wikiのコンテンツエリアをクリックした時にformの編集画面に切り替わるようにします。そのためにjeditableプラグインを利用するのでminifyバージョンをstaticディレクトリにダウンロードしておいてください。
これはajaxで通信するので編集画面に切り替わった際に元データをGETするためのAPIを用意しておきます。
app.pyに次の関数を追加します。
@app.route("/rst/<title>") def show_rst(title): content = WikiContent.query.filter_by(title=title).first() if content is None: abort(404) return content.body
単にrstなデータを返しているだけです。
続いてテンプレートも修正します。
show_content.html
{% extends "layout.html" %} {% block body %} <h1>{{content.title}}</h1> <div class="editable_textarea">{{content.html|safe}}</div> <p>{{content.date}}</p> <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"></script> <script type="text/javascript" src="{{url_for('static', filename='jquery.jeditable.mini.js')}}"></script> <script> $(".editable_textarea").editable("{{content.title}}", { type : 'textarea', submitdata: { _method: "post" }, name : 'body', loadurl : '/rst/' + '{{content.title}}', rows : 10, submit : 'OK', cancel : 'cancel', cssclass : "editable" }); </script> {% endblock %}
jeditableで操作するためにdiv要素にクラスを追加しています。
bodyの最後にjQueryとjeditableを呼び出しています。先ほどapp.pyに追加した関数はloadurlで呼び出すようになっています。
コンテンツをクリックすると編集画面になるので

日本酒に対する熱い思いをぶつけます。

ここまでのGitHub
reStructuredTextなWikiのための機能はひと通り揃いました。あとは見栄えを良くするためにStylus+Nib+Nibbleあたりでデザインをちょこまかいじればいいでしょう。

03032013 Python Flask SQLAlchemy
今回変更するのはapp.pyのみです。
SQLAlchemyを使ってデータを取得できるようになったので、データの追加、更新をできるようにします。そのためにはpython対話環境で行ったようにdb_sessionが必要なのでflaski.databaseモジュールをimportします。またリクエストの最後に、セッションの後片付けをする必要があります(shutdown_session)。
POST時にformにアクセスするのでflaskからrequestをインポートしています(1行目)。さらに、更新時を書き換えたいのでdatetimeモジュールもインポートしています。
from flask import Flask, render_template, abort, request from flaski.models import WikiContent from flaski.database import db_session from datetime import datetime app = Flask(__name__) app.config['DEBUG'] = True @app.teardown_request def shutdown_session(exception=None): db_session.remove() @app.route("/") def hello(): contents = WikiContent.query.all() return render_template("index.html", contents=contents) @app.route("/<title>", methods=["GET"]) def show_content(title): content = WikiContent.query.filter_by(title=title).first() if content is None: abort(404) return render_template("show_content.html", content=content) # 続く
GETでアクセスした場合にデータを取得、POSTでアクセスすると新規追加または更新を行いたいのでapp.routeのメソッドを限定します。
@app.route("/<title>", methods=["GET"])
POST用のコードが続きます。titleでデータを検索して存在しない場合には追加、存在する場合は更新処理をしています。bodyはformで渡されることを想定しています。
# 続き @app.route("/<title>", methods=["POST"]) def post_content(title=None): if title is None: abort(404) content = WikiContent.query.filter_by(title=title).first() if content is None: content = WikiContent(title, request.form["body"] ) else: content.body = request.form["body"] content.date = datetime.now() db_session.add(content) db_session.commit() return content.body if __name__ == "__main__": app.run()
HTMLでフォームを用意するのは面倒なので、今回はhttpieを利用してコマンドラインから操作してみます。
pipでインストールします
pip install httpie # $HOME/.virtualenvs/flaski/binにインストールされます
新規データを登録します。app.pyを実行してサーバーを起動しておくのを忘れないでください。
$ http --form POST http://localhost:5000/httpie body="test from httpie" HTTP/1.0 200 OK Content-Type: text/html; charset=utf-8 Content-Length: 16 Server: Werkzeug/0.8.3 Python/2.7.3 Date: Sun, 03 Mar 2013 04:09:36 GMT test from httpie
--formオプション(または-f)をつけるとformで送られます。データが新規に追加されていることをブラウザで確認します。
データが既に存在する場合には更新されることも確認します。
$ http --form POST http://localhost:5000/httpie body="modified from httpie"
FlaskiにPOST経由でのデータ追加、更新を実装しました。
ここまでのGitHub
03032013 Python Flask SQLAlchemy
先に用意したモデルをFlaskで使うにモデルをimportします。
ルートにアクセスしたらコンテンツのタイトル一覧を表示します。さらに、/titleにアクセスしたら内容を表示するようにします。
app.py
from flask import Flask, render_template, abort from flaski.models import WikiContent app = Flask(__name__) app.config['DEBUG'] = True @app.route("/") def hello(): contents = WikiContent.query.all() return render_template("index.html", contents=contents) @app.route("/<title>", methods=["GET"]) def show_content(title): content = WikiContent.query.filter_by(title=title).first() if content is None: abort(404) return render_template("show_content.html", content=content) if __name__ == "__main__": app.run()
database.pyでBaseクラスにqueryメソッドを追加しておいたので、WIkiContentクラスから、allで全件検索、filter_byでフィルタリングができるようになっています。
app.routeで<>で囲むと変数としてキャプチャしています。title名で検索をかけ、データが存在しない場合は404エラーを返します(abort(404))。
index.html
{% extends "layout.html" %}
{% block body %}
<h1>Flaski</h1>
<img src="{{url_for('static', filename='snake.jpg')}}" alt="snake"/>
<ul>
{% for content in contents %}
<li><a href="{{url_for('show_content', title=content.title)}}">{{content.title}}</a></li>
{% endfor%}
</ul>
{% endblock %}
for文でcontentsをループさせ、タイトルをリンク付きでリスト表示させる処理を新たに追加しています。タイトルはapp.pyから送る必要がないので、ハードコードするようにしました。
新たに個別のコンテンツ用のテンプレートも用意します
show_content.html
{% extends "layout.html" %} {% block body %} <h1>{{content.title}}</h1> <div>{{content.body}}</div> <p>{{content.date}}</p> {% endblock %}
コンテンツがリスト表示されることを確認します。

ここまでのGitHub
FlaskとSQLAlchemyを連携させてデータ検索、表示するようにしました。
03032013 Python Flask SQLAlchemy
SQLAlchemyを使ってModelをデザインしていきます。今回はdeclarativeを使い、RDBにSQLiteを利用します。
modelは一ヶ所で管理したいのでディレクトリを新たに用意します。
mkdir flaski # flaski/flaski cd flaski touch __init__.py
ディレクトリをmoduleとして呼び出したいので、__init__.pyという空のファイルを用意します。flaski/flaski以下は次のファイル構成になります。
├── flaski ├── __init__.py ├── database.py └── models.py
作成するのはWikiなのでタイトル、内容、タイムスタンプをデータベースに記録します。
models.py
from sqlalchemy import Column, Integer, String, Text, DateTime from flaski.database import Base from datetime import datetime class WikiContent(Base): __tablename__ = 'wikicontents' id = Column(Integer, primary_key=True) title = Column(String(128), unique=True) body = Column(Text) date = Column(DateTime, default=datetime.now()) def __init__(self, title=None, body=None, date=None): self.title = title self.body = body self.date = date def __repr__(self): return '<Title %r>' % (self.title)
WikiContentクラスではそれぞれの属性の型や主キー、ユニークかどうかなどを指定しています。__repr__メソッドでは出力した時にどう表示させるかを定義しています。
続いて、database.py
from sqlalchemy import create_engine from sqlalchemy.orm import scoped_session, sessionmaker from sqlalchemy.ext.declarative import declarative_base import os databese_file = os.path.join(os.path.abspath(os.path.dirname(__file__)), 'wiki.db') engine = create_engine('sqlite:///' + databese_file, convert_unicode=True) db_session = scoped_session(sessionmaker(autocommit=False, autoflush=False, bind=engine)) Base = declarative_base() Base.query = db_session.query_property() def init_db(): import flaski.models Base.metadata.create_all(bind=engine)
database.pyでは実際に利用されるデータベースエンジンの設定をしています。今回はSQLiteを使っています(6行目) init_dbはデータベース初期化のための関数です。
python対話環境を起動してデータベースを初期化します。
>>> from flaski.database import init_db >>> init_db()
flaski/flaski/wiki.dbが作成されているので確認してみます。
sqlite3 flaski/wiki.db sqlite> .schema CREATE TABLE wikicontents ( id INTEGER NOT NULL, title VARCHAR(128), body TEXT, date DATETIME, PRIMARY KEY (id), UNIQUE (title) );
続いて対話環境からデータを登録してみます
>>> from flaski.database import db_session >>> from flaski.models import WikiContent >>> c1 = WikiContent("Flask", "micro framework") >>> db_session.add(c1) >>> db_session.commit() >>> c2 = WikiContent("python", "pppython") >>> c3 = WikiContent("kobito", "kakure-momojiri") >>> db_session.add(c2) >>> db_session.add(c3) >>> db_session.commit()
確認してみます
$ sqlite3 flaski/wiki.db SQLite version 3.7.10 2012-01-16 13:28:40 Enter ".help" for instructions Enter SQL statements terminated with a ";" sqlite> select * from wikicontents; 1|Flask|micro framework|2013-03-03 09:23:03.721257 2|python|pppython|2013-03-03 09:23:03.721257 3|kobito|kakure-momojiri|2013-03-03 09:23:03.721257
ここまでのGitHub
SQLAlchemyのdeclarativeを使ってモデル構築と、pythonからデータベースの初期化、データの登録を行いました。
03032013 Python Flask SQLAlchemy
ディレクトリを用意します。
mkdir flaski
cd flaski
以下のコードをapp.pyとして保存します。ちなみにFlaskのサイトに載っているものです。
from flask import Flask app = Flask(__name__) @app.route("/") def hello(): return "Hello World!" if __name__ == "__main__": app.run()
Flaskで開発する準備が整っていれば、python app.pyと叩けば127.0.0.1:5000でウェブサーバーが起動します。
/にアクセスした場合にHello Worldという文字列を返すように設定して(4-6行目)、app.runでアプリを起動させています。
$ python app.py * Running on http://127.0.0.1:5000/

単なる文字列だと味気無いのでテンプレートエンジンを使ってもう少し複雑なHTMLを表示してみます。ディレクトリの構成を表示しておきます。
.
├── app.py
├── static
│ └── snake.jpg
└── templates
├── index.html
└── layout.html
cssや画像などのファイルはstaticというディレクトリに配置します。今回はsnake.jpgを表示してみます。
FlaskのテンプレートエンジンはJinja2です。Flask内でテンプレートを扱うにはrender_template関数を用い、テンプレートはtemplatesディレクトリに配置します。
templatesディレクトリにはlayout.html,index.htmlの2つのファイルを用意します。
layout.html
<!DOCTYPE html> <html> <head> <title>flaski</title> </head> <body> {% block body %}{% endblock %} </body> </html>
index.html
{% extends "layout.html" %}
{% block body %}
<h1>{{title}}</h1>
<img src="{{url_for('static', filename='snake.jpg')}}" alt="snake"/>
{% endblock %}
{{}}で囲むと変数を展開することができます。今回はtitleをapp.pyのrender_templateで渡しています。url_forはエンドポイントを指定するとURLに展開する関数です。
app.pyはrender_templateをインポートしてhello関数で使うようにします。
また今回からデバッグモードで動かすようにapp.configをいじっています(3行目)ので、ファイル更新時に自動リスタートしたり、エラーがあればブラウザにデバッグのための情報が出力されるようになります。
from flask import Flask, render_template app = Flask(__name__) app.config['DEBUG'] = True @app.route("/") def hello(): return render_template("index.html", title="Flaski") if __name__ == "__main__": app.run()
先ほどと同様にhttp://127.0.0.1:5000/にアクセスすると今度は画像つきのHTMLが表示されます。

ここまでのGitHub
FlaskでJinja2のテンプレートエンジンを使ってみました。
Flaskは何であって何でないかによると
Flask itself just bridges to Werkzeug to implement a proper WSGI application and to Jinja2 to handle templating.
ということなので、テンプレートエンジンはJinja2を利用するのがベストです。
Jinja2自体はその上に別の構文を被せることができるので、JadeやHamlも利用することができます。
個人的にはインデントでネストを表現するJadeの構文を気に入っているのでPyJadeを使うことが多いです。