ubuntu での /etc/resolv.conf の設定

ubuntu 12.04 からは resolvconf という仕組みで /etc/resolv.conf が管理されていて、直接編集しても再起動等で戻される。
正しくは

/etc/network/interfaces に

dns-nameservers 192.0.2.3 192.0.2.4
dns-search example.com example.jp

みたいな感じに設定できる。
もしくは /etc/resolvconf/resolv.conf.d/ 以下のファイルに resolv.conf と同じフォーマットで記入する。

設定反映は

 $ sudo resolvconf -u

らしいが、反映されなかった。何か条件があるぽい。
一応以下で無理矢理反映は出来たけどなんとかしたい

 $ sudo /etc/init.d/networking restart 
  • 参考サイト

ubuntu 12.04 で resolv.conf が書き換えられる - みちのぶのねぐら 工作室 旧館

Class-Based ViewからはじめるDjango入門

この記事は 2012 Pythonアドベントカレンダー (Webフレームワーク) 16日目 のエントリになります。
今回は DjangoのClass-Based Viewの紹介です。

Function-basedからClass-Basedへ

皆さん!View書いてますか、View。
Model-View-ControllerのViewじゃなくてModel-Template-ViewのViewです。


仕様変更なんて日常茶飯事なこの業界で、変更に強いウェブアプリを書くには
いかにViewを書かないかが週末の休日を守る最後の砦だと思う次第なわけですよ。


シンプルなViewと正しいモデル設計があれば仕様変更で
マミられたあなたの休日も半分くらいは残るはず!


とは言っても、画面とモデルの接点にいるViewはだいたい同じだけど
細かい大量の違いがあるためになかなか共通化が難しいでしょう。


画面は素人に見える分どうでもいい変更が大量にいれられてしまいますし
そこを守るよりはモデル側の設計を守る為に仕様変更と戦う事に注力したい所。


関数は引数で結果を変えるのは得意ですが、関数自体の処理を
ちょっとだけだけ変えたものをたくさん作るのはあまり得意ではありません。
そういえばそういうのが得意なやつがいました。


クラスです。


おぶじぇくとしこうってやつです。


いままでの関数ベースViewってのはDjangoチュートリアルでも作った以下のようなやつです。

# views.py
def index(request):
    latest_poll_list = Poll.objects.all().order_by('-pub_date')[:5]
    return render_to_response('polls/index.html',
                              {'latest_poll_list': latest_poll_list})
# urls.py
urlpatterns = patterns('',
    url(r'^polls/$', 'polls.views.index'),
)

普通ですね。ただのPollのリストをテンプレートに渡すだけのView関数です。


これがクラスベースになると

# views.py
class IndexView(TemplateView):
    template_name = 'polls/index.html'

    def get_context_data(self, **kwargs):
        latest_poll_list = Poll.objects.all().order_by('-pub_date')[:5]
        return {'latest_poll_list': latest_poll_list}
# urls.py
from polls.views import IndexView
urlpatterns = patterns('',
    url(r'^polls/$', IndexView.as_view()),
)

みたいに書きます。
これだけだと urls.pyでViewを直接importするのが面倒なくらいですかねー


便利なdjangoさんは色々汎用的な処理を用意していてくれて、テンプレートだけ表示するならそもそもViewを書かなくてもがあるのも今まで通りです。

urlpatterns = patterns('django.views.generic.simple',
    (r'^foo/$',  'direct_to_template', {'template': 'foo_index.html'}),
)

クラスベースではこうなります。

from django.views.generic import TemplateView
urlpatterns = patterns('',
    (r'^foo/$',  TemplateView.as_view(template_name="foo_index.html")),
)

まぁimportする分コードは増えた感があります。


他にもListを表示したりCRUDインターフェイスを用意するためのものなど一通りありますが
個別の細かいクラスベース汎用ビューの説明は ドキュメント のほうを参照してください。
リスト表示したり、詳細表示したり、リダイレクトしたりする汎用的なやつが色々あります。

で、クラスベースだと何がうれしいのか

やっと本題です。

Class-Based Viewはその名の通りクラスなので振る舞いを非常に容易に変更できます。
単に継承して上書きすればいいだけです。


Class-Based Viewは結局の所、純粋なPythonのクラスなので、テンプレートメソッドパターン wikipedia:Template_Method_パターン を中心としてオブジェクト指向のテクニックがそのまま使えます。(modelだとdjangoの models.Modelとの相性や、southとかsouthとかsouthとかsouthとかのせいで色々出来ない事があります)


そのため、個々の処理をMixinとして切り出しておき、最終クラスはそれらを組み立てるだけで完成させらるわけです。

class HogeView(TemplateView, FooMixin, BarMixin, FugaMixin):
    template_name = 'hoge/fuga.html'

これのすばらしい所は、最終的なクラス自体は別ですから、HogeViewだけでFooMixinに変更が必要なった場合はHogeViewで該当メソッド再定義して上書きすれば他のFooMxinを使っているクラスには一切修正をいれずに修正可能な所です。機能は共通化されつつも、部分変更は個別のクラスに閉じ込めておける。度重なる変更の末に共通処理がif文の嵐という未来とはこれでおさらば!


例えばテンプレートのレンダリングで、結果のオブジェクトが単数と複数の場合で使うテンプレートを変えたい時なんかは

import re
class MultiSingleTemplateView(TemplateView):
    is_single = False
    single_suffix = '_single'
    multi_suffix = '_multi'
    def get_template_names(self):
        suffix = self.single_suffix if self.is_single else self.multi_suffix
        return [re.sub(r'.html$', '{}.html'.format(suffix), self.template_name)]

みたいなのを書いて

class ResultView(MultiSingleTemplateView)
    template_name = 'poll/result.html'
    is_single = True
    
    def get_context_data(self, **kwargs):
        poll = Poll.get(kwargs.get('poll_id'))
        
        if len(poll.authors) > 1:
            self.is_single = False
        
        return {
            'poll': poll
        }

とするだけで単数の場合は poll/result_single.html が使われ
複数では poll/result_multi.html が使われます。

継承しての拡張なので

class ResultView(MultiSingleTemplateView)
    template_name = 'poll/result.html'
    
    def get_context_data(self, **kwargs):
        self.poll = Poll.get(kwargs.get('poll_id'))
        return {
            'poll': self.poll
        }
        
    @property
    def is_single(self)
        return len(self.poll.authors) == 1

みたいにプロパティにしても当然動きます。
(この例はかなり強引ですが・・・)


また、別のViewではresult_single.html, result_multi.htmlではなく、複数の時だけ result_n.html にしたい時は

class ComposeResultView(MultiSingleTemplateView)
    template_name = 'compoase/result.html'
    single_suffix = ''
    multi_suffix = '_n'

でOKなわけです。

今回はTemplateViewを拡張しましたが、当然ほかのdjango標準のgeneric viewも同じように拡張できます。

そんなこんなで、よりシンプルなViewを書いて変更に強いWebアプリケーションにするためにClass-Based Viewはかなり強力なツールではないかなと思う次第でした。



明日の 2012 Pythonアドベントカレンダー は @hdknr が django-social-authでGithub API を使ってみる(仮) を書くそうです。
OAuthは自分で書くと結構面倒ですから楽しみ!

Retina MacBook Pro買いました

2010 MidのMacBookPro 15inchも持っていたんですが
重くて結局2010 LateのMacBook Air 11inchを常用してました。

今回のRetina MacBookProは2kgと0.5kgほど軽くなりました。
Airよりかは大きくて重いですが、11inchではつらかったIDEでの開発などが超余裕という。

HDDも128G -> 512GB だしメモリも4GB->16GBなので快適この上ない。

あとは持ち歩く為のバッグを注文したのでそれが届けば完全移行かなー

いまさらながらMacBookAir Late2010のXbench

11inchのフルスペック版買ってたんですがXbenchとるのすっかり忘れてたので。
だいぶ使い込んでる(発売日にOnlineでBTOして購入)ので新品とはだいぶ違いますが
それでもこのスコア。


過去のとの比較。

Xbench テスト項目 MacBook Air Early2008(1.6Ghz HDD) MacBook Air Late2008(2.13Ghz SSD) MacBook Air Late2010(1.6Ghz SSD)
CPU Test 90.27 143.14 112.00
Thread Test 144.42 276.38 207.01
Memory Test 128.17 175.65 145.25
Quartz Graphics Test 99.48 161.52 131.14
OpenGL Graphics Test 17.41 134.44 95.90
User Interface Test 115.90 244.57 144.54
Disk Test 26.98 87.73 239.08

初代のGPU性能が低すぎるのはおいておいて、11inchモデルなのでLate2008からCPU/GPU、メモリなどの処理能力自体は低下しています。
しかしこの有り余る圧倒的なDisk性能がこの軽快感を生み出してるのがよくわかるベンチ結果でした。
同じSSDなのに3倍ちかく違うっておそろしいですね。