我正在使用Django + TastyPie + Backbone.js。我试图弄清楚如何在第一次请求时引导模型的初始数据,而不是在此处推荐的初始页面加载后获取它们:http: //backbonejs.org/#FAQ-bootstrap
有两个问题——一个是尝试加载单个 Django 模型,另一个是尝试序列化查询集。
例如,我有一个user
在上下文中调用的变量,它是一个 Django 用户,代表当前登录的用户。
我不想这样做:
var curUser = new App.Models.User({id: 1});
curUser.fetch();
并导致对服务器的另一个请求,因为我已经加载了用户模型。
我想将这些数据提升到一个主干模型中,例如:
var curUser = new App.Models.User({{user|json}});
(类似于How to load bootstrapped models of bone in 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 build RESTful response with only field information 和 id,但这需要在每个视图上编写此调用。
我当前的解决方案是to_dict
在 User 模型上添加一个方法 monkeypatched
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 模型本身不能序列化(不在一个列表中),只能序列化查询集。
我想很多人正在想办法在初始页面加载时(尤其是在使用 TastyPie 时)将他们的 django 模型数据引导到主干模型中,但我还没有找到一种合理的方法来做到这一点。
使用查询集,还有更多的 django 信息传递,我试图找出一种方法让序列化匹配来自 TastyPie api 的输出。
有没有人有将 django 模型和查询集提升为骨干模型的最佳实践?
更新:
我已更改我的 json 过滤器以使用 TastyPie 捆绑包,例如
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
这似乎更接近,使用单个模型,保持 DRY 与我在 TastyPie 中列出的我想要的字段,但还没有处理多个模型。我也不确定将它放在过滤器中是否有问题。
更新
也使用这个: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'))