bpmappersのサンプルコード。
DjangoのManyToManyFieldに対するアプローチ。
バージョン0.5でフィールドのkeyパラメータにドット区切りの文字列を指定できるようになったので、ListDelegateFieldの記述なんかもちょっと簡単にできる。
models.py
こんなモデルがあったとする
# coding: utf-8 from django.db import models class GroupManager(models.Manager): def private_groups(self): "非公開グループのみを返す" return self.get_query_set().filter(is_private=True) class Permission(models.Model): name = models.CharField(u'権限名', max_length=16, unique=True) def __unicode__(self): return self.name class Meta: verbose_name = u'権限' verbose_name_plural = verbose_name class Group(models.Model): name = models.CharField(u'グループ名', max_length=16) permissions = models.ManyToManyField(Permission, verbose_name=u'所持権限') is_private = models.BooleanField(u'非公開') objects = GroupManager() def __unicode__(self): return self.name class Meta: verbose_name = u'グループ' verbose_name_plural = verbose_name class User(models.Model): user_id = models.CharField(u'ユーザーID', max_length=16) email = models.EmailField(u'メールアドレス') groups = models.ManyToManyField(Group, verbose_name=u'所属グループ') def __unicode__(self): return self.user_id class Meta: verbose_name = u'グループ' verbose_name_plural = verbose_name
mappers.py
bpmappersでマッピングルールを作る。
UserMapperのgroupsで、keyパラメータにはGroupManagerのprivate_groupsメソッドを参照するように指定してる。
from bpmappers import ListDelegateField from bpmappers.djangomodel import ModelMapper from testapp.models import User, Group class GroupMapper(ModelMapper): class Meta: model = Group class UserMapper(ModelMapper): groups = ListDelegateField(GroupMapper, key='groups.private_groups') class Meta: model = User exclude = ['groups']
動かしてみる
コードはbitbucketに置いてます。
tokibito / sample_nullpobug / source / django / bpmappers_example — Bitbucket
virtualenvwrapperで環境を作って動かしてみる。
$ hg clone https://bitbucket.org/tokibito/sample_nullpobug/ $ cd sample_nullpobug/django/bpmappers_example/ $ mkvirtualenv bpmappers-test (bpmappers-test)$ pip install django==1.3.1 bpmapeprs==0.5 (bpmappers-test)$ python manage.py syncdb (bpmappers-test)$ python manage.py shell
>>> from testapp.models import User >>> user = User.objects.get(pk=1) >>> user.groups.all() [<Group: 管理者>, <Group: 閲覧者>] >>> from testapp.mappers import UserMapper >>> UserMapper(user).as_dict() {'id': 1, 'user_id': u'test', 'email': u'test@example.com', 'groups': [{'id': 1, 'name': u'\u7ba1\u7406\u8005', 'is_private': True, 'permissions': [{'id': 4, 'name': u'admin'}]}]}
groups以下はprivate_groupsで取得したデータになっている。
api.py
ちょっとわかりにくいのでjsonを出力するコードを書いてみる。
from django.utils import simplejson as json from testapp.models import User from testapp.mappers import UserMapper def get_user_json(pk): user = User.objects.get(pk=pk) user_dict = UserMapper(user).as_dict() result = json.dumps(user_dict, indent=2) return result
実行するとこんな感じ。
>>> from testapp.api import get_user_json >>> print(get_user_json(pk=1)) { "id": 1, "user_id": "test", "email": "test@example.com", "groups": [ { "id": 1, "name": "\u7ba1\u7406\u8005", "is_private": true, "permissions": [ { "id": 4, "name": "admin" } ] } ] }
exclude指定しないとうまくうごかないのはバグっぽい感じなので後で直すかな。