2009年11月22日日曜日

Django save する前に pk(id)を得る方法

 db.models.base.py のsave() メソッドあたりのコードを読んでみたが、ナニを書いているのかさっぱりわからなかったので、変数というかオブジェクトというかをデータベースに登録して管理というか、自前で計算することにした。

 models.py にこんな感じで追加
class LastId(models.Model):
lId = models.PositiveSmallIntegerField()
def get_id(self):
return self.lId

def inc_id(self):
self.lId = self.lId + 1
self.save()

def set_id(self,value):
self.lId = value
try:
lasId = LastId.objects.get(pk=1)
except:
lasId = LastId()
lasId.set_id(0)
lasId.id = 1
lasId.save()

class Item(models.Model):
def getId(self,name):
if self.id is None:
self.id = lasId.get_id() + 1
return u'cars/%s/%s' % (self.id,name)
...
def save(self, force_insert=False, force_update=False):
if lasId.get_id() + 1 == self.id:
lasId.inc_id()
super(Item,self).save(force_insert, force_update)
 難点は、manage.py syncdb を実行するときに try: ... lasId.save() をコメントアウトしないとエラーになること。インスタンス生成部分を別ソースに移動したりと色々やってみたが回避できない。from の循環参照を回避できればなんとかなりそうだったので C/C++ のようにプリプロセッサのマクロとかあればなんとかなりそうなんだが。
 該当箇所をコメントアウト -> syncdb を実行 -> コメントアウトを外す、とひと手間かかる。サーバーにインストールするときは、sqlite のデータベースも一緒にコピーする必要がある。

 「エレガントな解法」がありそうな気はするのだが...。

0 件のコメント:

コメントを投稿