如何将模型字段传递给 JsonResponse 对象

Posted

技术标签:

【中文标题】如何将模型字段传递给 JsonResponse 对象【英文标题】:How to pass model fields to a JsonResponse object 【发布时间】:2014-11-21 22:13:10 【问题描述】:

Django 1.7 引入了JsonResponse objects,我尝试使用它来向我的 ajax 请求返回值列表。

我想通过

>>> Genre.objects.values('name', 'color')
['color': '8a3700', 'name': 'rock', 'color': 'ffff00', 'name': 'pop', 'color': '8f8f00', 'name': 'electronic', 'color': '9e009e', 'name': 'chillout', 'color': 'ff8838', 'name': 'indie', 'color': '0aff0a', 'name': 'techno', 'color': 'c20000', 'name': "drum'n'bass", 'color': '0000d6', 'name': 'worldmusic', 'color': 'a800a8', 'name': 'classic', 'color': 'dbdb00', 'name': 'hiphop']

到一个 JsonResponse 对象。

但是,我的尝试失败了。

>>> JsonResponse('foo': 'bar', 'blib': 'blab') # works
<django.http.response.JsonResponse object at 0x7f53d28bbb00>

>>> JsonResponse(Genre.objects.values('name', 'color')) # doesn't work
Traceback (most recent call last):
  File "<console>", line 1, in <module>
  File "/home/marcel/Dokumente/django/FlushFM/env/lib/python3.4/site-packages/django/http/response.py", line 476, in __init__
    raise TypeError('In order to allow non-dict objects to be '
TypeError: In order to allow non-dict objects to be serialized set the safe parameter to False

这可能是由于Genre.objects.values()的数据结构不同。

如何正确地做到这一点?

[编辑]

safe=False 我明白了

>>> JsonResponse(Genre.objects.values('name', 'color'), safe=False)
Traceback (most recent call last):
  File "<console>", line 1, in <module>
  File "/home/marcel/Dokumente/django/FlushFM/env/lib/python3.4/site-packages/django/http/response.py", line 479, in __init__
    data = json.dumps(data, cls=encoder)
  File "/usr/lib/python3.4/json/__init__.py", line 237, in dumps
    **kw).encode(obj)
  File "/usr/lib/python3.4/json/encoder.py", line 192, in encode
    chunks = self.iterencode(o, _one_shot=True)
  File "/usr/lib/python3.4/json/encoder.py", line 250, in iterencode
    return _iterencode(o, 0)
  File "/home/marcel/Dokumente/django/FlushFM/env/lib/python3.4/site-packages/django/core/serializers/json.py", line 109, in default
    return super(DjangoJSONEncoder, self).default(o)
  File "/usr/lib/python3.4/json/encoder.py", line 173, in default
    raise TypeError(repr(o) + " is not JSON serializable")
TypeError: ['color': '8a3700', 'name': 'rock', 'color': 'ffff00', 'name': 'pop', 'color': '8f8f00', 'name': 'electronic', 'color': '9e009e', 'name': 'chillout', 'color': 'ff8838', 'name': 'indie', 'color': '0aff0a', 'name': 'techno', 'color': 'c20000', 'name': "drum'n'bass", 'color': '0000d6', 'name': 'worldmusic', 'color': 'a800a8', 'name': 'classic', 'color': 'dbdb00', 'name': 'hiphop'] is not JSON serializable

什么是有效的

>>> JsonResponse(list(Genre.objects.values('name', 'color')), safe=False)
<django.http.response.JsonResponse object at 0x7f53d28bb9e8>

但是没有更好的方法来从 Model 对象生成字典吗?

【问题讨论】:

您是否尝试按照错误消息中的说明进行操作? @speendo safe=False 是否也出现同样的错误?也许在将ValuesQuerySet 传递给list() 之后尝试一下:JsonResponse(list(Genre.objects.values('name', 'color'))) @speendo: .values() 返回一个字典列表。如果你愿意,你可以创建一个新字典 dict(genres=Genre.objects...) 并使用它。 我只是在这里猜测,但也许现在list() 可以解决问题。 dict(genres=list(Genre.object...)). @Tiago 确实如此。只是我,还是从 django 模型中生成 JSON 响应对象非常棘手?无论如何-您想制定一个答案以便我接受吗? 【参考方案1】:

为了将来的参考,.values() 返回一个 ValuesQuerySet,其行为类似于一个充满字典的可迭代对象,因此使用 list() 将创建一个包含所有字典的 list 的新实例。有了它,您可以创建一个新的 dict 并对其进行序列化。

response = JsonResponse(dict(genres=list(Genre.objects.values('name', 'color'))))

IIRC,拥有一个以列表为根的 JSON 对象是不安全的,这可能就是 Django 抱怨的原因。我现在找不到任何相关的参考资料来提供来源,抱歉。

【讨论】:

***.com/a/26833156/179583 的答案使用来自 django.core 的 serializers,这可能很方便将整个模型导出,但必须将已经序列化的 JSON 传递给 JsonResponse 似乎很奇怪/恶心。我更喜欢这个答案的技术,尤其是当我只需要每个模型的几个字段时。 我一直在寻找这样的答案! 在序列化函数中,您可以传递一个可选的fields 参数,它只会返回指定的字段而不是整个对象作为JSON。【参考方案2】:

要将非字典值传递给使用 Genres.object.values('name','color') 检索的 JsonResponse,您可以简单地将安全参数设置为 false,它将返回 JSON。

from django.http import JsonResponse

def django_json(request):
    data = Genres.object.values('name','color')
    return JsonResponse(data, safe=False)

这应该返回您指定的值的 JSON 列表。查看我的文章How to Return a Json Response with Django,了解有关其工作原理的更多详细信息。

或者,如果您想将查询集返回为 JSON,您可以使用 Django 的核心序列化器,如下所示:

from django.core.serializers import serialize
from django.http import JsonResponse
from .models import Genre

def django_models_json(request):
    qs = Genre.objects.all()
    data = serialize("json", qs, fields=('name', 'color'))
    return JsonResponse(data)

这将返回与上面相同的内容。

【讨论】:

以上是关于如何将模型字段传递给 JsonResponse 对象的主要内容,如果未能解决你的问题,请参考以下文章

从Django REST中的函数返回JsonResponse

如何在 DJango 中将 RawQuerySet 结果作为 JSONResponse 传递?

如何将值从字段传递给 Odoo 13 中的向导?

我如何从模型中获取字段并计算一些字段并将它们传递给我的模板?

来自 Django 的 JsonResponse 没有将提到的键值对发送到 Reactjs

如何将模型动作传递给 Tkinter MVC 中的查看按钮?