無駄なソース
今日は可愛いキャラクターと一緒にlxmlの練習☆
import urllib2
from lxml import etree
print ''.join([etree.parse(urllib2.urlopen('http://endlessx.homelinux.com/blog/detail/24/'), parser=etree.HTMLParser()).xpath('.//div[@class="contents"]/p[position()='+x+']/text()')[0][y:z] for x, y, z in (('3', 47, 48), ('3', 81, 82), ('3', 65, 66), ('24', 0, 1), ('19', 28, 29), ('24', 73, 75))])
Twistedのインストール
Twisted がなんなのかわかってもいないのにインストールしてみた.
順に色々調べていくのは,面倒なので訳もわからないままー進んじまえ!という感じでインストールに進みました. 特に大したコトではないがー個人メモとして残しておく.
$ wget http://tmrc.mit.edu/mirror/twisted/Twisted/2.5/Twisted-2.5.0.tar.bz2
$ tar jxvf Twisted-2.5.0.tar.bz2
$ cd Twisted-2.5.0
$ sudo /usr/local/python/bin/python2.5 setup.py install
と何も考えずやったら, ImportError: you need zope.interface installed (http://zope.org/Products/ZopeInterface/)
とエラーがでたので,またもわからないですがーzope.interfaceをインストールしろということなのでダウンロードして来たのですが,よく見ると Twisted を解凍した中にzopeが含まれていたので,そちらでインストールしてみました.
$ cd Twisted-2.5.0/zope.interface-3.3.0/
$ /usr/local/python/bin/python2.5 setup.py build
$ sudo /usr/local/python/bin/python2.5 setup.py install
てな感じ!! あとは,ちょっとipython使って簡単に試してみました. http://www.liris.org/blog/566/ こちらのサイトを参考にやってみましてーブラウザ越しにアクセスしたらー確認できたのでー恐らく成功なんでしょう.
内容の薄いBLOGで申し訳ないっす.
Django FormModelにてトラブった
今日はDjango! ずっと古いリビジョンで動かしていたので,最新版のDjangoに耐えられるように修正. maxlengthをmax_lengthへ,escapeを削除,form_for_model/form_for_instanceからFormModelへ…
前者の2つは特に簡単なコトなんですが,FormModelでチト苦労した. というのも,BookmarkやBlogのタグ付け(ManyToManyField)を「del.icio.us っぽく」していた. 詳細は nobu さんの ManyToManyFieldをちょっとdel.icio.usっぽく を見てみて下さい. という訳で,自分のBookmarkは下記のような感じになっていた.(この部分は個人メモを兼ねているので飛ばしてもらってかまいません.)
#####
# project/bookmark/forms.py
#
class MultiTagInput(forms.TextInput):
def render(self, name, value, attrs=None):
if isinstance(value, QuerySet):
value = ' '.join([t.name for t in value])
return super(MultiTagInput, self).render(name, value, attrs)
class MultiTagField(forms.Field):
def __init__(self, **kwargs):
kwargs.update({
'widget' : MultiTagInput,
})
super(MultiTagField, self).__init__(**kwargs)
def clean(self, value):
super(MultiTagField, self).clean(value)
values = []
for name in value.replace('\u3000', ' ').split(' '):
if len(name):
tag, created = Label.objects.get_or_create(name=name)
values.append(tag.id)
if not len(values):
raise forms.ValidationError(_('This field is required.'))
return values
ENTRY_FORMFIELDS['labels'] = MultiTagField
def entry_form_callback(f, **kwargs):
try:
return ENTRY_FORMFIELDS[f.name](**kwargs)
except:
return f.formfield(**kwargs)
#####
# project/bookmark/views.pyの一部
#
def edit(request, id):
""" 更新処理 """
bookmark = get_object_or_404(Bookmark, pk=id)
f = forms.form_for_instance(bookmark, formfield_callback=entry_form_callback)
form = f(request.POST.copy() or None)
このforms.pyModelFormに対応するように,コールバック関数(entry_form_callback)の削除したり, 下記のようなModelFormを追記した.
class MultiTagInput(forms.TextInput):
def render(self, name, value, attrs=None):
if isinstance(value, QuerySet):
value = ' '.join([t.name for t in value])
return super(MultiTagInput, self).render(name, value, attrs)
class MultiTagField(forms.Field):
def clean(self, value):
super(MultiTagField, self).clean(value)
values = []
for name in value.replace('\u3000', ' ').split(' '):
if len(name):
tag, created = Label.objects.get_or_create(name=name)
values.append(tag.id)
if not len(values):
raise forms.ValidationError(_('This field is required.'))
return values
class LabelForm(forms.ModelForm):
""" Form for Bookmark Label """
class Meta:
model = Label
fields = ('name',)
exclude = ('created_at', 'updated_at')
class BookmarkForm(forms.ModelForm):
""" Form for Bookmark """
labels = MultiTagField(widget=MultiTagInput) # ここで上記のFieldを設定.
class Meta:
model = Bookmark
fields = ('title', 'url', 'comment', 'labels')
exclude = ('created_at', 'updated_at')
そして,views.pyでは,
def edit(request, id):
""" 更新処理 """
bookmark = get_object_or_404(Bookmark, pk=id)
form = BookmarkForm(request.POST.copy() or None, instance=bookmark)
てな感じに修正してうまくいくと思ったのですが….だめだったぁ〜.新規作成は成功なのですが,更新しようとするとタグフィールドにタグ名(label.name)ではなくIDになってしまった. ということで,コードを追いかけてみました.
今まで使っていたform_for_instanceは下記の部分でManyToManyにうまく対応してやっているように見える.
# site-packages/django/newforms/models.py
def form_for_instance(instance, form=BaseForm, fields=None,
formfield_callback=lambda f, **kwargs: f.formfield(**kwargs)):
warn("form_for_instance is deprecated. Use ModelForm instead.",
PendingDeprecationWarning, stacklevel=3)
model = instance.__class__
opts = model._meta
field_list = []
for f in opts.fields + opts.many_to_many:
if not f.editable:
continue
if fields and not f.name in fields:
continue
current_value = f.value_from_object(instance) # <= フィールドにでる値
formfield = formfield_callback(f, initial=current_value)
if formfield:
field_list.append((f.name, formfield))
base_fields = SortedDict(field_list)
return type(opts.object_name + 'InstanceForm', (form,),
{'base_fields': base_fields, '_model': model,
'save': make_instance_save(instance, fields, 'changed')})
けどもFormModel部分では,
# site-packages/django/newforms/models.py
class BaseModelForm(BaseForm):
def __init__(self, data=None, files=None, auto_id='id_%s', prefix=None,
initial=None, error_class=ErrorList, label_suffix=':',
instance=None):
opts = self._meta
if instance is None:
# if we didn't get an instance, instantiate a new one
self.instance = opts.model()
object_data = {}
else:
self.instance = instance
object_data = model_to_dict(instance, opts.fields, opts.exclude) # <= 自分の希望通りの動きをしてくれてないような感じ….
# if initial was provided, it should override the values from instance
if initial is not None:
object_data.update(initial) # <= updateしてる.
BaseForm.__init__(self, data, files, auto_id, prefix, object_data, error_class, label_suffix)
ん〜とコードを眺めていると「initial」を渡してあげればーupdateしてるのでー views.py を下記のように変更して,とりあえず,目的は達成!
def edit(request, id):
""" 更新処理 """
bookmark = get_object_or_404(Bookmark, pk=id)
# タグフィールドに表示したいものをinitialで渡してあげる.
form = BookmarkForm(request.POST.copy() or None, instance=bookmark, initial={'labels' : bookmark.labels.all()})
もっとうまい方法があるのかなぁ〜.このままだとーあとでコード見たときに何しているかわからないよね? 多くの部分を省いて説明しているので,わけのわからない内容になってしまったかも….
しっかし,久しぶりにDjango触れてー楽しかった☆
寝る前の5分間でPython
string.maketransを使う.
In [1]: import string
In [2]: trans = string.maketrans('aug', 'AUG')
In [3]: mRNA = 'gaauaggcgccattagauaugguuuguuuugcgcauuaauauagcgauuuu'
In [4]: mRNA.translate(trans)
Out[4]: 'GAAUAGGcGccAttAGAUAUGGUUUGUUUUGcGcAUUAAUAUAGcGAUUUU'
ん?あっ!そうか!ですよね...勘違いした!アホだ! 「5分です!!」 では,おやすみなさい.