Как сериализовать cleaned_data, если он содержит модели? - PullRequest
2 голосов
/ 12 июня 2011

Я пытаюсь сериализовать некоторые данные формы, чтобы я мог вставить их в скрытое поле, пока пользователь не будет готов отправить всю форму (подумайте о мастере).

Я пытаюсь это:

print simplejson.dumps(vehicle_form.cleaned_data)

Но я продолжаю получать ошибки вроде этого:

<VehicleMake: Honda> is not JSON serializable

На самом деле мне просто нужно, чтобы вывести PK для "Honda".

Это не 'либо не работает:

print serializers.serialize('json', vehicle_form.cleaned_data)

Дает:

'str' object has no attribute '_meta'

Предположительно, потому что он перебирает ключи, которые являются строками, тогда как я думаю, что он ожидает набор запросов, который я неесть.

Так как мне это сделать?


Хорошо, пока я придумал это:

from django.utils.simplejson import JSONEncoder, dumps, loads
from django.utils.functional import curry
from django.db.models import Model
from django.db.models.query import QuerySet
from django.core.serializers import serialize

class DjangoJSONEncoder(JSONEncoder):
    def default(self, obj):
        if isinstance(obj, Model):
            return obj.pk
        elif isinstance(obj, QuerySet):
            return loads(serialize('json', obj, ensure_ascii=False))
        return JSONEncoder.default(self, obj)

json_encode = curry(dumps, cls=DjangoJSONEncoder)
json_decode = loads

На основании ответов, которые янайдено [здесь] [1].Сейчас я пытаюсь это сделать:

json = json_encode(vehicle_form.cleaned_data)
data = json_decode(json)
vehicle = Vehicle(**data)

Первые две строки работают отлично, но третья приводит к исключению:

Cannot assign "3": "Vehicle.model" must be a "VehicleModel" instance.

Близость!Не знаю, как с этим справиться, хотя ...

1 Ответ

0 голосов
/ 13 июня 2011

Это что-то вроде хака, но я не знаю лучшего способа:

try:
    vehicle_data = simplejson.loads(request.POST['vehicle_data'])
except ValueError:
    vehicle_data = []
vehicle_data.append(vehicle_form.raw_data())
request.POST['vehicle_data'] = simplejson.dumps(vehicle_data)

Он захватывает данные JSON из скрытого поля в вашей форме и декодирует их в Python dict.Если он не существует, он начинает новый список.Затем он добавляет новые необработанные / неочищенные данные, перекодирует их и сбрасывает в скрытое поле.

Чтобы это работало, вам нужно либо сделать копию данных POST (request.POST.copy()), чтобыон становится изменяемым или взламывает его, как я это сделал: request.POST._mutable = True

В шаблоне формы я поместил это:

<input type="hidden" name="vehicle_data" value="{{request.POST.vehicle_data}}" />

И, наконец, для доступа к необработанным данным для формы, которую я добавилэти методы:

from django.forms import *

def _raw_data(self):
    return dict((k,self.data[self.add_prefix(k)]) for k in self.fields.iterkeys())

def _raw_value(self, key, value=None):
    if value is None:
        return self.data[self.add_prefix(key)]
    self.data[self.add_prefix(key)] = value

Form.raw_data = _raw_data
Form.raw_value = _raw_value
ModelForm.raw_data = _raw_data
ModelForm.raw_value = _raw_value

Так как .data возвращает слишком много данных (фактически, он просто возвращает данные POST, которые вы изначально передали), плюс у него есть префиксы, которые я не хотел.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...