如何在常规Django视图中向tastypie资源添加数据

3 投票
1 回答
1324 浏览
提问于 2025-04-17 18:32

我在尝试在一个普通的Django视图中包含tastypie资源时遇到了问题。我希望这个视图返回的内容像这样(是根据视图中生成的查询集,而不是来自tastypie的常规获取参数):

{
    "success": bool,
    "message": string,
    "error": string,
    "objects": [
        {
            "field_one": bar,
            "field_two": foo
        }
        ... more objects ...
    ]
}

这里的对象列表是一个序列化的tastypie资源列表,而成功、消息和错误则是来自视图中的其他地方。

现在,我还没找到办法在构建更大的字典之前,避免把序列化的资源变成字符串,所以我目前的代码是这样的:

{
    "success": bool,
    "message": string,
    "error": string,
    "objects": [
        "{"field_one": bar, "field_two": foo..."}",
        "{"field_one": baz, "field_two": foobar..."}",
        ...
    ]
}

这样做的主要目的是保持模型的JSON表示一致,以减少直接使用tastypie API和在这些视图中返回的数据之间的摩擦。我在想解决方案可能是以某种方式在每个资源上使用full_dehydrate方法,而不进行序列化,然后把它们添加到更大的字典中,最后再序列化这个字典,但我不确定该用什么序列化器。或者,也许还有更好的方法。

1 个回答

1

像往常一样,把这个写下来让我找到了一个临时的解决办法。也许有人能给出一些建议,让这个方法更好。

我用这个来准备一个查询集,以便进行序列化:

def serialize_queryset(resource_class, queryset):
    # hand me a queryset, i give you dehydrated resources
    resource = resource_class()
    dd = {}

    # make meta
    dd['meta'] = {}
    dd['meta']['limit'] = 1000
    dd['meta']['next'] = None
    dd['meta']['offset'] = 0
    dd['meta']['previous'] = None
    dd['meta']['total_count'] = len(queryset)

    # objects
    dd['objects'] = []
    for obj in queryset:
        bundle = resource.build_bundle(obj=obj)
        dehydrated_obj = resource.full_dehydrate(bundle)
        dd['objects'].append(dehydrated_obj)

    # return dict
    return dd

我使用的是tastypie.serializer里的序列化器。在一个示例视图中使用它大概是这样的:

from tastypie.serializer import Serializer

serializer = Serializer()

def my_view(request):

    #... do some other view stuff ...

    # prepare a queryset for serialization
    queryset = MyModel.objects.filter(is_cool=True)
    data = serialize_queryset(MyModel, queryset)

    # add in custom stuff, determined earlier in the view somewhere
    data['success'] = success
    data['message'] = message
    data['error'] = error

    # serialize and return response
    data = serializer.serialize(data)
    return HttpResponse(data, mimetype='application/json')

这个方法似乎有效。也许你能发现这个方法有什么不好的地方,或者有什么改进的办法?

撰写回答