Djangoアプリ全体で使う変数をコンテキストプロセッサで提供
組み込み Template とかをみてると {{ MEDIA }} とかが出てきますが、これを自前で作る方法。同じアプリを複数サイトで立ち上げる必要が出てきて、区別の為、アプリごとにユニークな名前を表示したい。ただ、それだけの用途に使いました。
(Django 1.7 の admin のように基底クラスの中で変数を定義して継承、もしくはCookieに値をセット、なども気づいたのですが、今回は修正が少なくて済む context processor を用意する方法を選択)
環境:
Template と Context
Template 上で扱いたいオブジェクトや値は、Viewからcontextに入れて渡すというのが通常の流れ。
view.py
class IndexView(TemplateView): template_name = 'index.html' ... context['application_name'] = 'HogeHoge'
app/templates/index.html
<h1>{{ application_name }}</h1>
しかし、全Viewに対してアプリ名を渡すとなると、各Viewのcontextにアプリ名を渡していく修正が発生するので手間がかかる。
Context Processor で Context に値を追加
そこで、新しく必要な値を渡す コンテキスト プロセッサを作り、context を生成する度に、特定の変数を渡せるようにします( {{ MEDIA }} のような)。
dateutil で 曖昧な日付をパースする
python の dateutil ライブラリ。標準の datetime.strptime で日付を構文解析するよりも手軽にパースすることができます。2.x/3.x 両対応。
今回、このようなフォーマットの日付をパースしたのですが、表記が曖昧なので、結果が揺れてしまいました。
In [1]: import dateutil.parser In [11]: dateutil.parser.parse('30/09/2015') Out[11]: datetime.datetime(2015, 9, 30, 0, 0) In [12]: dateutil.parser.parse('28/09/2015') Out[12]: datetime.datetime(2015, 9, 28, 0, 0) In [13]: dateutil.parser.parse('11/10/2015') Out[13]: datetime.datetime(2015, 11, 10, 0, 0)
そこで dayfirst=True をつけて明示化して解決。
In [14]: dateutil.parser.parse('11/10/2015', dayfirst=True) Out[14]: datetime.datetime(2015, 10, 11, 0, 0)
ちなみに daifirst, yearfirst ともにデフォルトは False らしいです。
ちょっとした課題は、賢人が過去に考えて解決策だしてくれてるんだと実感した次第です。
Python仮想環境ツール一覧 virtualenvwrapper, direnvとか
Pythonなど新しいバージョンがリリースされる言語は、プロジェクトや勉強に合わせたパッケージ用意したりと、1つの環境で作業しているとグチャグチャになります。
そこで1台のPC上に独立した個別環境を複数作れる、Python仮想環境を用意するツールを利用します。沢山あるなーって思ったので一覧にしてみました。
仮想環境ツールの一覧
ツール名 | 切替コマンド | 概要 |
direnv | 特定ディレクトリに cd するだけ。複数言語に対応 | environment switcher for the shell。GO言語 |
anyenv | 特定ディレクトリに cd するだけ。複数言語に対応 | simple wrapper for rbenv style environment managers。bashスクリプト |
pyenv | 特定ディレクトリに cd するだけ | Simple Python Version Management。bashスクリプト |
venv/pyvenv | source activate/deactivate | Python 3.3以降に内蔵。PEP 405 |
virtualenvwrapper | 切替えコマンド workon/deactivate | bashスクリプト |
virtualenv | 切替えコマンド activate/deactivate | bashスクリプト/Windowsバッチ |
self と cls とかが何か気になって調べてみた + @staticmethod
python 書いてると”ふと”気になる self と cls を調べメモ。
なんで書くのかなぁという疑問が解消すると、結構気持ちよくかけるようになった気がします。書いてる人には、あたりまえ話ですいません。
# 各種メソッドとかスコープについては、何も説明ないので、別のサイトみて確認ください
self について
クラスの中で定義する インスタンス・メソッド (instance method)では、必ず第一引数に self を書きます。
class MyClass(object): def instance_method(self, x, y): print x+y my = MyClass() my.instance_method(1,2) 3
第一引数に self と書くのですが、呼び出し時には 第二引数以降を渡します。selfには「インスタンス自身」が入ります。自動的入る仕様なのですね。
なお、Official ドキュメントにもありますが、文字列としては self 以外でも大丈夫とのこと。ただし慣習的に self を使うことになってるので、そうしましょうとのこと。
9. クラス — Python 2.7ja1 documentation
Beautiful Soup 4.4.0 で extract() を使うとDOM treeが壊れる?
Python で Beautiful Soup 4.4.0 を使った時に遭遇した問題。stackoverflow でも取り上げられていて、取り敢えずは 4.3.2 に戻すことで対処しました。
環境
問題点
次のようなコードで、html中からscriptタグを除去していたところ 4.0 の環境でおかしな動作が起きた。
soup = BeautifulSoup(page_html, 'lxml') [s.extract() for s in soup('script')]
この処理の後、soup('body') の結果が None になってしまうという現象が発生。また、[s.extract() for s in soup('script')] を何度実行しても消せないscriptタグが出たりと。いずれも4.3.2では、起きてなかった問題でした。
対策
前述の stackoverflowのエントリー を見つけて読んだ所、 extract() 後に 二重改行がはいることでおかしくなるとの回答がある。
解決方法として 1. str(soup) を再度BeautifulSoupでパースする 2. html5lib パーサーを使う が提案されていた。また別の回答としては 4.3.2 だと大丈夫ともある。
僕の環境の場合、4.4.0必須ではなかったのと pip で管理していたのでバージョン固定が簡単にできるということで、4.3.2 固定にして使うことにした。
# pip install beautifulsoup4==4.3.2