Djangoでもemacsでgrep-gems コマンド

Djangoはpydocでみてもクラスやメソッドがよく分からないことが多いし、ドキュメント見るよりソースみた方が早いこともある。

railsでの紹介だけど
emacs での grep-gems コマンド
の方法でemacs.elを設定したら結構良い感じになった。

subversionの.svnも拾っちゃうのが邪魔だけど、それ以外は問題なし。
/site-packages/~ のを参照すると操作ミスでファイルを変更しちゃいそうなので
別途同じリビジョンのものを落として、それを見るようにしてます。

reSTを導入するも

import re, urllib
register = Library()


BRACKET_LINK_RE=re.compile("\[\[(.+?)\]\]")

def restructuredtext_rigid(value):
	try:
		from docutils.core import publish_parts
	except ImportError:
		return value
	else:
		parts = publish_parts(source=value, settings_overrides={'doctitle_xform': False},writer_name="html4css1")
	return parts["fragment"]

@register.filter
def wikify(value):
	"""Makes WikiWords"""
	def quote_link(ob):
		word=ob.group(1)
		return r'<a href="/wiki/%s">%s</a>' % (urllib.quote(word), word)
	#return restructuredtext_rigid(value)
	value = restructuredtext_rigid(value)
	return BRACKET_LINK_RE.sub(quote_link, value)

昨日のwikiの内容を変更するカスタムフィルターにrestructuredtextを導入しようかとあれこれテストしてみました。


    
      続きを読む
    
    
  

カスタムフィルター

カスタムフィルターはテンプレートの内容になんらかの変更を行うときに使います。
例えばwikiの文章のなかに

abcd[[test]]dcba

のような記述があったときに

abcd<a href="/wiki/test/">test</a>bcda

と変換させたいときは

テンプレートを以下のようにして

{% load wikitags %}
{{ page.title }}
    <h1>{{ page.title }}</h1>
    <div class="body">
        {{ page.body|wikify }}
    </div>

カスタムフィルターを以下のようにすると良い。
/myproject/wiki/templatetags/wikitags.py

from django.template import Library
from django.conf import settings

register = Library()

@register.filter
def wikify(value):
	"""Makes WikiWords"""
	import re
	wikifier = re.compile("\[\[(.+?)\]\]")
	return wikifier.sub(r'<a href="/wiki/\1/">\1</a>', value)

テンプレートの

{% load wikitags %}

でtemplatetagsのwikitagsを読み込み

{{ page.body|wikify }}

でwikitagsのwikifyという関数にpage.bodyを引数で渡すことによって正規表現で書き換えられた文字列が返ってきます。

参考(というかそのまま)
http://e-scribe.com/news/171

slugの使い方

model.pyが以下の場合で

class Page(models.Model):
	title=models.CharField(unique=True, maxlength=200)
	body=models.TextField()
	date=models.DateField(auto_now=True)
	class Admin:
		pass

	def __repr__(self):
		return self.title


id=1, title="test", body="test test"
のデータあり、
url.pyを以下にした場合

info_dict={'queryset': Page.objects.all()}

page_dict={'model': Page}

urlpatterns=patterns('',
(r'^(?P<object_id>\d+)/$','django.views.generic.list_detail.object_detail',
 info_dict ),
(r'^(?P<slug>\w+)/$','django.views.generic.list_detail.object_detail',
 dict(info_dict, slug_field='title')),
)
http://localhost:8000/simplewiki/1/

でも

http://localhost:8000/simplewiki/test/

でも
同じインスタンス
/mytemplate/simplewiki/page_detail.html
に反映されます。

正規表現で取り出した(?P\w+)は、titleであると
slug_field='title'で伝えてるわけですね。


また、

veiw.genericは便利だけど、そのままでは使えないケースが多いので、
view.pyにコピーして弄るか、
自前のgenericをmyporjectの下に作った方がよいかもしれません。

saveとdeleteの前処理と後処理

DjangoはModelにあれこれ処理を書くことができるのが特徴だと思うのですが、
test/modeltestsをみてたら
save_delete_hooks/model.py
にsave()やdelete()に関する説明がありました。

自分のアプリのmodel.pyで作るクラスは
django/db/models/base.py
にあるModelクラスを継承して作るのですが、

save(),delete()の場合は継承元のsuperクラスに任せるようになっているようです。

"""
13. Adding hooks before/after saving and deleting

To execute arbitrary code around ``save()`` and ``delete()``, just subclass
the methods.
"""

from django.db import models

class Person(models.Model):
    first_name = models.CharField(maxlength=20)
    last_name = models.CharField(maxlength=20)

    def __repr__(self):
        return "%s %s" % (self.first_name, self.last_name)

    def save(self):
        print "Before save"
        super(Person, self).save() # Call the "real" save() method
        print "After save"

    def delete(self):
        print "Before deletion"
        super(Person, self).delete() # Call the "real" delete() method
        print "After deletion"

API_TESTS = """
>>> p1 = Person(first_name='John', last_name='Smith')
>>> p1.save()
Before save
After save

>>> Person.objects.all()
[John Smith]

>>> p1.delete()
Before deletion
After deletion

>>> Person.objects.all()
[]
"""

この機能によって、事前に確認をとったり、処理後にリダイレクトしたりしてるのですね。

simplewiki

djangoの勉強をちょこっとだけ、railsのscaffold程度のもの
view.pyは何も書かずに「汎用ビュー (generic view) 」だけのテスト

python manage.py startapp simplewiki

setting.pyの
INSTALLED_APPに'myproject.simplewiki'を追加
TEMPLATE_DIRSにテンプレートのパス
DATABASE関連
を書いて
下記のファイルを作って

python manage.py sql simlewiki
python magage.py syncdb
python manage.py runserver

でとりあえず動くかも
明日はslugだったかな?を勉強してform関連のドキュメントを読んで
他の人のコードを読んでみよう。

==myproject/urls.py
from django.conf.urls.defaults import *

urlpatterns = patterns('',
   (r'^simplewiki/', include('myproject.simplewiki.urls')),
   (r'^admin/', include('django.contrib.admin.urls')),
)

==simplewiki/urls.py

from django.conf.urls.defaults import *
from myproject.simplewiki.models import Page
info_dict={'queryset': Page.objects.all()}
page_dict={'model': Page}

urlpatterns = patterns('',
   (r'^$','django.views.generic.list_detail.object_list', info_dict ),
   (r'^(?P<object_id>\d+)/$','django.views.generic.list_detail.object_detail', 
info_dict ),
   (r'^(?P<object_id>\d+)/edit/$','django.views.generic.create_update.update_object',
 dict(page_dict, post_save_redirect="/simplewiki/")),
   (r'^(?P<object_id>\d+)/delete/$','django.views.generic.create_update.delete_object',
 dict(page_dict, post_delete_redirect="/simplewiki/")),
   (r'^add/$','django.views.generic.create_update.create_object',
 dict(page_dict, post_save_redirect="/simplewiki/")),
)

==simplewiki/models.py

from django.db import models

# Create your models here.
class Page(models.Model):
	title=models.CharField(unique=True, maxlength=200)
	body=models.TextField()
	date=models.DateField(auto_now=True)
	class Admin:
		pass

	def __repr__(self):
		return self.title

==myproject/mytemplate/simplewiki/page_list.html
<ul>
{% for page in object_list %}
   <li><a href="/simplewiki/{{ page.id }}">{{ page.title }}</a></li>
{% endfor %}
<a href="/simplewiki/add">create page</a>
</ul>

==myproject/mytemplate/simplewiki/page_detail.html
<h1>{{ object.title }}</h1>
<p>{{ object.body }}</p>
{{ object.date }}<br/>
<a href="edit">edit</a><br/>
<a href="delete">delete</a><br/>

==myproject/mytemplate/simplewiki/page_form.html
{% if object %}
<form method="post" action="/simplewiki/{{ object.id }}/edit/">
{% else %}
<form method="post" action="/simplewiki/add/">
{% endif %}
      {{ form.title }}<br/>
      {{ form.body }}<br/>
      <input type="submit" name="type" />
</form>

==myproject/mytemplate/simplewiki/page_confirm_delete.html
<form method="post" action="/simplewiki/{{ object.id }}/delete/">
{{ object.title }} <br/>
<input type="submit" name="type" />
</form>