Как вы сериализуете экземпляр модели в Django?

99

Существует много документации о том, как сериализовать модель QuerySet, но как вы просто сериализуете в JSON поля экземпляра модели?

  • 0
    Хотя, похоже, вы можете сериализовать набор запросов из 1 объекта, но вы не можете использовать классы из django.core для этого. Любая конкретная причина не использовать сериализовать набор запросов?
  • 1
    Сериализатор наборов запросов упаковывает результат в два слоя больше, чем нужно. Таким образом, вы должны сделать data [0] .fields.name вместо data.name.
Показать ещё 2 комментария
Теги:
django-models
serialization

12 ответов

166
Лучший ответ

Вы можете легко использовать список для переноса требуемого объекта и что все, что сериализаторы django должны правильно сериализовать, например:

from django.core import serializers

# assuming obj is a model instance
serialized_obj = serializers.serialize('json', [ obj, ])
  • 6
    Но в ответ вам необходимо индексировать нулевой элемент объекта JSON, чтобы получить сериализованный объект. Просто кое-что отметить.
  • 8
    А как насчет сериализации всех ссылочных объектов вместе с корневым объектом?
Показать ещё 6 комментариев
35

Чтобы избежать обертки массива, удалите его перед возвратом ответа:

import json
from django.core import serializers

def getObject(request, id):
    obj = MyModel.objects.get(pk=id)
    data = serializers.serialize('json', [obj,])
    struct = json.loads(data)
    data = json.dumps(struct[0])
    return HttpResponse(data, mimetype='application/json')

Я нашел этот интересный пост по этому вопросу:

http://timsaylor.com/convert-django-model-instances-to-dictionaries

Он использует django.forms.models.model_to_dict, который выглядит как идеальный инструмент для работы.

  • 5
    если это лучший способ сериализации одной модели в django, то это ужасно, так как не нужно десериализовать json и сериализовать его обратно.
  • 0
    @ Херберт, возможно. Но это так. Если у вас есть лучший способ, я все уши. Это не должно иметь большого практического недостатка, поскольку выборка и / или повторное кодирование одного объекта не должны быть настолько ресурсоемкими. Превратите это в вспомогательную функцию или добавьте / добавьте ваши объекты в качестве нового метода, если вы хотите скрыть ужас.
Показать ещё 1 комментарий
26

Если вы имеете дело со списком экземпляров модели, лучше всего использовать serializers.serialize(), он идеально подойдет вам.

Однако вы столкнулись с проблемой с попыткой сериализации одного объекта, а не list объектов. Таким образом, чтобы избавиться от разных хаков, просто используйте Django model_to_dict (если я не ошибаюсь, serializers.serialize() тоже полагается на него):

from django.forms.models import model_to_dict

# assuming obj is your model instance
dict_obj = model_to_dict( obj )

Теперь вам просто нужен один прямой вызов json.dumps для сериализации его в json:

import json
serialized = json.dumps(dict_obj)

Что это!:)

  • 3
    это не работает с полями UUID, иначе должно быть ясно
  • 1
    терпит неудачу с полями datetime . Решил это следующим образом: json.loads(serialize('json', [obj]))[0] а сериализатором - django.core.serializers.serialize
9

Похоже на то, о чем вы спрашиваете, включает сериализацию структуры данных экземпляра модели Django для обеспечения совместимости. Другие плакаты верны: если вы хотите, чтобы сериализованная форма использовалась с приложением python, которое может запрашивать базу данных через Django api, тогда вам понадобится сериализовать набор запросов с одним объектом. Если, с другой стороны, то, что вам нужно, - это способ повторно раздуть экземпляр модели где-то в другом месте, не касаясь базы данных или не используя Django, тогда вам нужно немного поработать.

Вот что я делаю:

Во-первых, я использую demjson для преобразования. Это было то, что я нашел первым, но это может быть не самое лучшее. Моя реализация зависит от одной из ее функций, но с другими преобразователями должны быть аналогичные способы.

Во-вторых, реализуйте метод json_equivalent для всех моделей, которые могут потребоваться для сериализации. Это волшебный метод для demjson, но, вероятно, вы захотите подумать о том, какую реализацию вы выберете. Идея состоит в том, что вы возвращаете объект, который напрямую конвертируется в json (т.е. Массив или словарь). Если вы действительно хотите сделать это автоматически:

def json_equivalent(self):
    dictionary = {}
    for field in self._meta.get_all_field_names()
        dictionary[field] = self.__getattribute__(field)
    return dictionary

Это не поможет вам, если у вас нет полностью плоской структуры данных (нет ForeignKeys, только числа и строки в базе данных и т.д.). В противном случае вам следует серьезно подумать о правильном способе реализации этого метода.

В-третьих, вызовите demjson.JSON.encode(instance), и у вас есть то, что вы хотите.

  • 0
    Я еще не пробовал код, но я просто хотел указать на некоторые ошибки в нем. Это instance._meta.get_all_field_names (), а getattribute является функцией, поэтому должен иметь (), а не [].
  • 0
    Хорошие моменты. Напрягите до плохого набора текста.
Показать ещё 1 комментарий
7

Если вы спрашиваете, как сериализовать один объект из модели, а вы знаете, вы получите только один объект в наборе запросов (например, используя objects.get), тогда используйте что-то вроде:

import django.core.serializers
import django.http
import models

def jsonExample(request,poll_id):
    s = django.core.serializers.serialize('json',[models.Poll.objects.get(id=poll_id)])
    # s is a string with [] around it, so strip them off
    o=s.strip("[]")
    return django.http.HttpResponse(o, mimetype="application/json")

который предоставит вам что-то вроде формы:

{"pk": 1, "model": "polls.poll", "fields": {"pub_date": "2013-06-27T02:29:38.284Z", "question": "What up?"}}
  • 0
    Но это уберет все квадратные скобки, а не только внешние. Лучше? "o = s [1: -1]"?
4

Я решил эту проблему, добавив в мою модель метод сериализации:

def toJSON(self):
    import simplejson
    return simplejson.dumps(dict([(attr, getattr(self, attr)) for attr in [f.name for f in self._meta.fields]]))

Здесь многословный эквивалент для тех, кто не относится к однострочным:

def toJSON(self):
    fields = []
    for field in self._meta.fields:
        fields.append(field.name)

    d = {}
    for attr in fields:
        d[attr] = getattr(self, attr)

    import simplejson
    return simplejson.dumps(d)

_meta.fields - упорядоченный список полей модели, к которым можно получить доступ из экземпляров и из самой модели.

  • 3
    Хотя идея может показаться хорошей на первый взгляд, следует отметить, что использование этого подхода имеет последствия. Вы привязываете один конкретный выход сериализации к своей модели.
3

Использовать список, он решит проблему

Шаг 1:

 result=YOUR_MODELE_NAME.objects.values('PROP1','PROP2').all();

Шаг 2:

 result=list(result)  #after getting data from model convert result to list

Шаг 3:

 return HttpResponse(json.dumps(result), content_type = "application/json")
  • 0
    Похоже, что он все равно будет сериализован как массив json (объектов), а не как голый объект, о чем и спрашивал OP. ау, это ничем не отличается от обычного метода сериализации.
2

Здесь мое решение для этого, которое позволяет вам легко настраивать JSON, а также организовывать связанные записи

Сначала реализуем метод на модели. Я называю json, но вы можете называть его любым, например:

class Car(Model):
    ...
    def json(self):
        return {
            'manufacturer': self.manufacturer.name,
            'model': self.model,
            'colors': [color.json for color in self.colors.all()],
        }

Тогда в представлении я делаю:

data = [car.json for car in Car.objects.all()]
return HttpResponse(json.dumps(data), content_type='application/json; charset=UTF-8', status=status)
  • 0
    В Python 3 это становится car.json()
2

как об этом:

def ins2dic(obj):
    SubDic = obj.__dict__
    del SubDic['id']
    del SubDic['_state']
return SubDic

или исключить все, что вы не хотите.

2
ville = UneVille.objects.get(nom='lihlihlihlih')
....
blablablab
.......

return HttpResponse(simplejson.dumps(ville.__dict__))

Я возвращаю dict моего экземпляра

чтобы он возвращал нечто вроде {'field1': value, "field2": value,....}

  • 0
    это сломается: TypeError: <django.db.models.base.ModelState object at 0x7f2b3bf62310> is not JSON serializable
1

Для сериализации и десериализации, используйте следующее:

from django.core import serializers

serial = serializers.serialize("json", [obj])
...
# .next() pulls the first object out of the generator
# .object retrieves django object the object from the DeserializedObject
obj = serializers.deserialize("json", serial).next().object
1

Кажется, вы не можете сериализовать экземпляр, вам придется сериализовать QuerySet одного объекта.

from django.core import serializers
from models import *

def getUser(request):
    return HttpResponse(json(Users.objects.filter(id=88)))

Я закончил выпуск django svn, поэтому это может быть не в более ранних версиях.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню