Django - объект типа decimal не является сериализуемым json и преобразуется в данные модели в представлениях

rows = fetchall()
resultList = []
resultModel = []
resultDict = []
for row in rows:
    resultModel.append(ResultModel(*row)) # Object of type ResultModel is not JSON serializable
    resultList.append(list(row)) # Rows returned by pyodbc are not JSON serializable
    resultDict.append(dict(zip(columns, row))) # Object of type Decimal is not JSON serializable

Мне нужно получить json-версию данных в представлении. Для этого я пытаюсь получить дамп данных в формате JSON. Использование json.dumps(resultDict) вызывает ошибку.

Ошибки при попытке получить результаты, отличные от модели, закомментированы для справки. Вариант dict(zip()) наиболее близок к тому, что я хочу. ResultDict дает мне пару JSON (ключ, значение), которую я могу использовать. Но это дает мне ошибку в результирующих данных, которые включают "DecimalField". Есть ли способ иметь десятичные разряды без ошибок в возвращаемых данных? Похоже, что это было бы просто, что бы поддерживал Django, поэтому я не уверен, что мне что-то не хватает!

https://github.com/pyeve/eve-sqlalchemy/issues/50

Кроме того, могу ли я обработать ResultModel непосредственно в json-дампе в представлении, вместо того, чтобы настраивать 2 набора результатов (одних и тех же данных, только с разным форматированием) для отправки обратно в представление из модели?

ОБНОВИТЬ: Я понял это. Поскольку это хранимый процесс / прямой запрос, сопоставление ORM не работает, когда мы используем dict(zip(columns, row)) следует использовать имена столбцов из запроса базы данных. Затем для получения JSON выполните json.dumps(myDict)

Альтернативное решение: В моделях return [ResultModel(*row) for row in rows]

Просмотры:

results = Get-model
json = serializers.serialize("python", results, fields=('Column1', 'Column2')

Но это также дает мне название модели. Есть ли способ получить только часть .fields каждого возвращенного списка?

[ поля: {Column1: "1", Column2: "2"}, модель: "app_name.resultmodel", pk: "" ]

Действительно, JSON не имеет десятичного типа, поэтому json.dumps не знает, что делать с вашим DecimalField. Но Django делает поддерживает это в своих сериализаторах, которые предназначены именно для этого. Или используйте Django REST Framework, у которого есть гораздо более настраиваемые.

Daniel Roseman 13.09.2018 20:18

Я получил это с помощью - from django.core.serializers.json import DjangoJSONEncoder, а затем json.dumps(data, cls=DjangoJSONEncoder), но мне пришлось вернуть как ResultModel, так и версию JSON. Мне нужны оба, есть ли способ отправить один, а затем скрыть его в представлениях / шаблонах по мере необходимости?

Loser Coder 13.09.2018 20:19

Кроме того, предполагается, что сериализатор отделен от view.py? Я очень новичок в использовании Django, поэтому хочу попробовать и использовать лучшие практики

Loser Coder 13.09.2018 20:20
4
3
6 417
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Попробуйте расширить JSONEncoder

import json
from decimal import Decimal

class DecimalEncoder(json.JSONEncoder):
    def default(self, obj):
        if isinstance(obj, Decimal):
            return float(obj)
        return json.JSONEncoder.default(self, obj)

# Usage:
d = Decimal("42.5")
json.dumps(d, cls=DecimalEncoder)

отредактировал мой вопрос. У меня есть 2 объекта, которые я создаю и отправляю в представление из модели. Есть ли способ отобразить данные модели (ResultModel (row)) из объекта / словаря столбцов json? {'col1': 'val1', 'col2':'val2'} {'col1':'res2', 'col2':'row2'}, но это не массив / список объектов, поэтому цикл не работает напрямую в шаблоне. Попытка использовать json.loads(jsonData) тоже не работает.

Loser Coder 13.09.2018 20:55

Другие вопросы по теме