Как сериализовать Django queryset.values() в json?

У меня есть модель со многими полями, однако для этой задачи мне нужно только 3 из этих полей. Когда я пытаюсь сериализовать набор .values, я получаю исключение:

Объект 'dict' не имеет атрибута '_meta'

Это мой код:

queryset = myModel.objects.filter(foo_icontains=bar).values('f1', 'f2', 'f3')
serialized_q = serializers.serialize('json', queryset, ensure_ascii=False)

person bash-    schedule 04.10.2011    source источник
comment
Какое исключение вы получаете?   -  person Constantinius    schedule 04.10.2011
comment
вы пробовали это с queryset = myModel.objects.filter(foo_icontains=bar).values('foo.f1', 'foo.f2', 'foo.f3')?   -  person Constantinius    schedule 04.10.2011
comment
возможный дубликат преобразования django ValuesQuerySet в объект json   -  person Davor Lucic    schedule 04.10.2011


Ответы (5)


Сериализаторы Django могут только сериализовать набор запросов, values() возвращает не набор запросов, а объект ValuesQuerySet. Поэтому избегайте использования values(). Вместо этого укажите поля, которые вы хотите использовать в values(), в методе сериализации следующим образом:

Посмотрите на этот SO вопрос, например

objectQuerySet = ConventionCard.objects.filter(ownerUser = user)
data = serializers.serialize('json', list(objectQuerySet), fields=('fileName','id'))

Вместо использования objectQuerySet.values('fileName','id') укажите эти поля, используя параметр fields для serializers.serialize(), как показано выше.

person Davor Lucic    schedule 04.10.2011
comment
Да, я знаю, что .values() возвращает список, однако simplejson.dumps дает мне jsondata is not JSON serializable, ValuesQuerySet имеет форму: [{'key1': 'value1', 'key2': 'value2'}] - person bash-; 04.10.2011
comment
Да, это зависит от того, как выглядят данные, первый пример из связанного ответа - это то, что вы ищете. - person Davor Lucic; 04.10.2011
comment
@bash- просто сначала вызовите list(). - person Daniel Roseman; 04.10.2011
comment
Да, list(ValuesQuerySet) должен возвращать список, который затем можно сериализовать с помощью simplejson. - person Davor Lucic; 04.10.2011
comment
спасибо, просто примечание, в вопросе SO, который вы связали, этот подход запрашивает БД для всех полей, а затем подмножает его для 2 полей, или он будет запрашивать БД только для этих 2 полей? - person bash-; 04.10.2011
comment
Я думаю, что он будет запрашивать все поля, возможно, вы могли бы использовать only при запросе. Хотя я не совсем уверен. Отладьте его, чтобы увидеть, как выглядит запрос. - person Davor Lucic; 04.10.2011
comment
Помните, что это сработает, только если вы получите один результат. Решение list() будет работать в обоих случаях. - person Davor Lucic; 04.10.2011
comment
@rebus спасибо, раньше это не работало, потому что было DecimalField, и его нельзя было сериализовать - person bash-; 04.10.2011

Как уже говорили другие люди, сериализаторы Django не могут обрабатывать ValuesQuerySet. Однако вы можете сериализовать с помощью стандартного json.dumps() и преобразовать свой ValuesQuerySet в список с помощью list(). Если ваш набор включает поля Django, такие как Decimals, вам нужно будет передать DjangoJSONEncoder. Таким образом:

import json
from django.core.serializers.json import DjangoJSONEncoder

queryset = myModel.objects.filter(foo_icontains=bar).values('f1', 'f2', 'f3')
serialized_q = json.dumps(list(queryset), cls=DjangoJSONEncoder)
person Andre Gregori    schedule 13.08.2015
comment
Наконец, это помогло мне, я хочу, чтобы набор запросов был преобразован в JSON, а затем возвращен в шаблон. - person Kyle_397; 06.03.2020

Сделать список из objectQuerySet:

data_ready_for_json = list( ConventionCard.objects.filter(ownerUser = user).values('fileName','id') )
person Max    schedule 29.11.2013
comment
Это было самое быстрое и простое решение для меня. Я добавил JsonResponse(data_ready_for_json, safe=False), и он отлично работал в вызове Ajax. - person Kalob Taulien; 06.03.2018
comment
У меня была аналогичная проблема. Приведенное выше решение с использованием списка (queryset) работало очень хорошо. Спасибо Макс! - person user2162611; 01.07.2020

Мое решение, оно работает нормально

from django.core.serializers import serialize
import json

permission_list = Permission.objects.all().order_by('-id')
permission_serialize= json.loads(serialize('json', permission_list))
return JsonResponse({'data': permission_serialize})
person Ashish Sondagar    schedule 07.12.2019
comment
Почему вы serialize(), а затем loads() только для того, чтобы JsonResponse снова сериализовать список. Это лишняя, ненужная работа. - person Code-Apprentice; 21.06.2021

Просто введите dict для каждого элемента и создайте json с помощью json.dumps:

json.dumps([dict(item) for item in SomeModel.objects.all().values('id', 'title')])
person Pavel Patrin    schedule 19.04.2015