Django + TastyPie + Backbone.jsを使用しています。ここで推奨されているように、最初のページの読み込み後にモデルをフェッチするのではなく、最初のリクエストでモデルの初期データをブートストラップする方法を見つけようとしています: http://backbonejs.org/#FAQ-bootstrap
2 つの問題があります。1 つは単一の Django モデルをロードしようとするもので、もう 1 つはクエリセットをシリアル化しようとするものです。
user
例として、Django ユーザーであり、ログインしている現在のユーザーを表すコンテキストで呼び出される変数があります。
私はこれをしたくありません:
var curUser = new App.Models.User({id: 1});
curUser.fetch();
ユーザーモデルが既にロードされているため、サーバーに別のリクエストを発生させます。
このデータを次のようなバックボーン モデルにブーストラップしたいと考えています。
var curUser = new App.Models.User({{user|json}});
( Django でバックボーンのブートストラップ モデルをロードする方法に似ていますが、すべてを json に変換する各ビューで特別なケースを実行したくありません)
json に変換するカスタム テンプレート フィルターを作成した場所
def json(object):
"""Return json string for object or queryset.
"""
if isinstance(object, QuerySet):
return mark_safe(serialize('json', object))
if isinstance(object, Model):
object = object.to_dict()
return mark_safe(simplejson.dumps(object))
register.filter('json', json)
問題は、django モデルをシリアル化すると、次のような結果が得られることです。
[{"pk": 1, "model": "auth.user", "fields": {"username": "user@gmail.com", "first_name": "Jeremy", "last_name": "Keeshin", "is_active": true, "is_superuser": false, "is_staff": false, "last_login": "2013-07-15T22:31:02", "groups": [], "user_permissions": [], "password": "passwordhash", "email": "user@gmail.com", "date_joined": "2012-06-14T00:59:18"}}]'
私が本当に欲しいのは、TastyPie を使用して定義した API と一致する json 表現です。
class UserResource(ModelResource):
"""A resource for the User model."""
class Meta:
queryset = User.objects.all()
resource_name = 'user'
authorization = Authorization()
fields = ['username', 'first_name', 'last_name', 'id']
filtering = {
'username': ALL,
'email': ALL,
'first_name': ALL,
'last_name': ALL
}
ここでは、モデルをシリアル化するときにすべてではなく、いくつかのフィールドのみが返されます。Django では特定のフィールドのみをシリアル化できることは知っていますが、これらのフィールドはモデルごとに設定されているため、すべてのビューにその呼び出しを含めたくありません。
ここで同様の回答が表示されますDjango Serialize Queryset to JSON to construct RESTful response with only field information and idですが、これにはすべてのビューでこの呼び出しを記述する必要があります。
私の現在の解決策はto_dict
、ユーザーモデルにモンキーパッチを適用したメソッドを追加することです
def to_dict(self):
"""Return a subset of fields as a dictionary."""
return {
'id': self.id,
'first_name': self.first_name,
'last_name': self.last_name,
'email': self.email
}
これはシリアライズしやすいからです。さらに、django モデルは (1 つのリストではなく) 単独でシリアル化することはできません。シリアル化できるのはクエリセットのみです。
多くの人が、最初のページ読み込み時に (特に TastyPie を使用する場合に) django モデル データをバックボーン モデルにブートストラップするための良い方法を考え出していると思いますが、これを行うための合理的な方法を見つけられませんでした。
クエリセットを使用すると、さらに多くの django 情報が渡されます。シリアライゼーションを TastyPie API からの出力と一致させる方法を見つけようとしています。
django モデルとクエリセットをバックボーン モデルにブーストするためのベスト プラクティスはありますか?
アップデート:
次のようなTastyPieバンドルを使用するようにjsonフィルターを変更しました
from core.api import UserResource
from core.api import UserProfileResource
from tastypie.serializers import Serializer
def json(object):
"""Return json string for object or queryset."""
TYPE_TO_RESOURCE = {
'User': UserResource,
'UserProfile': UserProfileResource
}
Resource = TYPE_TO_RESOURCE[object.__class__.__name__]
r = Resource()
bundle = r.build_bundle(object)
r.full_dehydrate(bundle)
s = Serializer()
return mark_safe(s.serialize(bundle, 'application/json'))
ソース: http://django-tastypie.readthedocs.org/en/latest/cookbook.html#using-your-resource-in-regular-views
これはより近いようで、単一のモデルで作業し、TastyPie にリストしたいフィールドを DRY のままにしますが、まだ複数のモデルを処理していません。これをフィルターに入れることが問題になるかどうかもわかりません。
アップデート
これも使用してください:https://gist.github.com/1568294/4d4007edfd98ef2536db3e02c1552fd59f059ad8
def json(object):
"""Return json string for object or queryset."""
TYPE_TO_RESOURCE = {
'User': UserResource,
'UserProfile': UserProfileResource,
}
if isinstance(object, QuerySet):
Resource = TYPE_TO_RESOURCE[object[0].__class__.__name__]
r = Resource()
bundles = [r.build_bundle(model) for model in object]
bundle = [r.full_dehydrate(b) for b in bundles]
elif isinstance(object, Model):
Resource = TYPE_TO_RESOURCE[object.__class__.__name__]
r = Resource()
bundle = r.build_bundle(object)
r.full_dehydrate(bundle)
else:
mark_safe(simplejson.dumps(object))
s = Serializer()
return mark_safe(s.serialize(bundle, 'application/json'))