3

我正在使用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'))
4

0 回答 0