Django에서 모델 인스턴스를 어떻게 직렬화합니까?


157

모델 QuerySet을 직렬화하는 방법에 대한 많은 문서가 있지만 모델 인스턴스의 필드를 JSON으로 직렬화하는 방법은 무엇입니까?


쿼리 세트를 1 개의 객체로 직렬화 할 수있는 것처럼 보이지만 클래스를 사용하여 django.core이를 수행 할 수는 없습니다 . 쿼리 세트를 직렬화하지 않는 특별한 이유가 있습니까?
Jack M.

1
queryset serializer는 결과를 두 개 이상의 레이어로 래핑합니다. 따라서 data.name 대신 data [0] .fields.name을 수행해야합니다.
Jason Christa

그것이 내가 생각했던 거죠. 장고 백엔드에 대한 GWT 인터페이스를 작성할 때도 같은 문제가 발생했습니다. 다윗이 무언가 위에있을 것 같습니다.
Jack M.

답변:


242

목록을 사용하여 필요한 객체를 쉽게 래핑 할 수 있으며 장고 시리얼 라이저가 올바르게 직렬화하는 데 필요한 모든 것입니다.

from django.core import serializers

# assuming obj is a model instance
serialized_obj = serializers.serialize('json', [ obj, ])

9
그러나 이에 대한 응답으로 직렬화 된 객체를 얻으려면 JSON 객체의 0 요소를 색인화해야합니다. 주목할 점이 있습니다.
Davor Lucic

10
그리고 루트 객체와 함께 모든 참조 객체를 직렬화하는 것은 어떻습니까?
paweloque

1
[0]@DavorLucic이 제안한 것처럼 마지막 줄의 끝에서 원하지 않습니까? 그리고 목록 리터럴에서 쉼표를 사용할 필요가 없습니다 (PEP8의 사랑을 위해).
hobs

역 직렬화에는 추가 단계가 필요합니다.
Zags

5
이것은 나를 위해 작동하지 않았습니다. 장고 AttributeError '튜플'객체가 더 속성 '_meta을'이 발생합니다
adamF

71

모델 인스턴스 목록을 다루는 가장 좋은 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.dumpsjson으로 직렬화 하려면 한 번만 호출하면됩니다.

import json
serialized = json.dumps(dict_obj)

그게 다야! :)


6
UUID 필드에서는 실패합니다. 그렇지 않으면 명확해야합니다.
Alvin

2
datetime필드 와 함께 실패 합니다. json.loads(serialize('json', [obj]))[0]serializer가있는 동안 이 방법으로 해결django.core.serializers.serialize
Lal Zada

43

배열 랩퍼를 피하려면 응답을 리턴하기 전에 제거하십시오.

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를 사용하는데 이는 작업을위한 완벽한 도구처럼 보입니다.


9
이것이 장고에서 단일 모델을 직렬화하는 가장 좋은 방법이라면 json을 직렬화 해제하고 다시 직렬화 할 필요가 없으므로 끔찍합니다.
Herbert

아마도 허버트. 그러나 거기에 있습니다. 더 좋은 방법이 있다면 나는 모두 귀입니다. 단일 객체 페치 및 디 / 리코딩이 리소스 집약적이어서는 안되므로 실질적인 단점은 없습니다. 공포를 숨기려면 도우미 기능으로 만들거나 새로운 방법으로 객체를 확장 / 혼합하십시오.
Julian Julian

1
공포를 숨기는 것은 문제가 아니며 아마도이 해결책도 아닙니다. 놀랍게도 이것이 장고의 최선의 방법이라는 것입니다.
Herbert

14

이것에 대한 좋은 대답이 있으며 언급되지 않은 것에 놀랐습니다. 몇 줄로 날짜, 모델 및 기타 모든 것을 처리 할 수 ​​있습니다.

모델을 처리 할 수있는 사용자 지정 인코더를 만듭니다.

from django.forms import model_to_dict
from django.core.serializers.json import DjangoJSONEncoder
from django.db.models import Model

class ExtendedEncoder(DjangoJSONEncoder):

    def default(self, o):

        if isinstance(o, Model):
            return model_to_dict(o)

        return super().default(o)

이제 json.dumps를 사용할 때 사용하십시오.

json.dumps(data, cls=ExtendedEncoder)

이제 모델, 날짜 및 모든 항목을 직렬화 할 수 있으며 배열 또는 직렬화 및 직렬화하지 않아도됩니다. 당신이 가진 것은 모두 사용자 정의 default메소드에 추가 할 수 있습니다 .

Django의 네이티브 JsonResponse를 다음과 같이 사용할 수도 있습니다.

from django.http import JsonResponse

JsonResponse(data, encoder=ExtendedEncoder)
``

3
이 솔루션은 간단하고 우아합니다. 엔코더 json.dumpsjson.dump방법 모두에 사용할 수 있습니다 . 이 방법으로 json으로 변환하기 전에 사용자 정의 객체를 사용하거나 다른 메소드 호출을 추가하므로 애플리케이션의 워크 플로우를 변경할 필요가 없습니다. 엔코더에 변환 코드를 추가하기 만하면됩니다.
Claudiu

11

당신이 요구하는 것은 상호 운용성을 위해 Django 모델 인스턴스의 데이터 구조를 직렬화하는 것과 관련이 있습니다. 다른 포스터는 정확합니다 .Django의 api를 통해 데이터베이스를 쿼리 할 수있는 파이썬 응용 프로그램에서 직렬화 된 양식을 사용하려면 하나의 객체로 쿼리 세트를 직렬화하고 싶습니다. 반면에 데이터베이스를 건드 리거나 장고를 사용하지 않고 모델 인스턴스를 다른 곳에 다시 팽창시키는 방법이 필요한 경우 약간의 작업이 필요합니다.

내가하는 일은 다음과 같습니다.

먼저 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)하면 원하는 것을 가질 수 있습니다.


아직 코드를 시도하지 않았지만 오류가 있음을 지적하고 싶었습니다. instance._meta.get_all_field_names ()이며 getattribute 는 함수이므로 []가 아닌 ()가 있어야합니다.
Jason Christa

FK 외에도 날짜 / 시간 필드에는 작동하지 않습니다 (demjson.JSON.encode에 마법이없는 경우)
Skylar Saveland

8

모델에서 단일 객체를 직렬화하는 방법을 묻고 쿼리 세트에서 객체를 하나만 얻는다는 것을 알고 있다면 (예 : 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's up?"}}

그러나 외부 브래킷뿐만 아니라 모든 대괄호가 제거됩니다. 보다 나은? "o = s [1 : -1]"?
Julian

5

모델에 직렬화 방법을 추가하여이 문제를 해결했습니다.

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
아이디어가 처음에는 좋아 보이지만이 방법을 사용하면 결과가 발생한다는 것을 지적해야합니다. 하나의 특정 직렬화 출력을 모델에 연결합니다.
Jonas Geiregat

이 방법은 모델마다 정의되므로 @JonasGeiregat는 어떻습니까? 안타깝게도 이것은 필드와 인스턴스의 기본 키가 모두 포함 된 json 객체를 반환하는 유일한 방법 인 것 같습니다.
dopatraman

5

여기에 내 솔루션이 있습니다.이 솔루션을 사용하면 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)

Python 3에서는 다음과 같이됩니다.car.json()
T.Coutlakis

4

사용 목록, 문제를 해결할 것입니다

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")

이것은 OP가 요구 한 벌거 벗은 객체가 아닌 (객체의) JSON 배열로 직렬화되는 것처럼 보입니다. 이제는 일반 직렬화 방법과 다르지 않습니다.
Julian

1
JSON 직렬화 오류와 함께 실패합니다. 쿼리 셋 객체는 직렬화 할 수 없습니다
dopatraman

4

직렬화 및 직렬화 해제하려면 다음을 사용하십시오.

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 = next(serializers.deserialize("json", serial)).object

'제너레이터 객체에'다음 '속성이 없습니다. 어떤 생각?
user2880391 2016 년

1
@ user2880391 파이썬 3에 대해 이것을 업데이트했습니다.
저쪽으로 네요

4

.values() 모델 인스턴스를 JSON으로 변환하는 데 필요한 것입니다.

.values ​​() 문서 : https://docs.djangoproject.com/en/3.0/ref/models/querysets/#values

라는 모델과 사용 예제 프로젝트 .

참고 : Django Rest Framework를 사용하고 있습니다.

    @csrf_exempt
    @api_view(["GET"])
    def get_project(request):
        id = request.query_params['id']
        data = Project.objects.filter(id=id).values()
        if len(data) == 0:
            return JsonResponse(status=404, data={'message': 'Project with id {} not found.'.format(id)})
        return JsonResponse(data[0])

유효한 ID의 결과 :

{
    "id": 47,
    "title": "Project Name",
    "description": "",
    "created_at": "2020-01-21T18:13:49.693Z",
}

3

단일 모델 객체 를 클라이언트에 대한 json 응답 으로 반환하려는 경우 다음 과 같은 간단한 솔루션을 수행 할 수 있습니다.

from django.forms.models import model_to_dict
from django.http import JsonResponse

movie = Movie.objects.get(pk=1)
return JsonResponse(model_to_dict(movie))

2

Django Serializerpython형식 과 함께 사용하십시오 .

from django.core import serializers

qs = SomeModel.objects.all()
serialized_obj = serializers.serialize('python', qs)

형식 json과 의 차이점은 무엇입니까 python?

json으로 포맷 한 결과를 반환 str하는 반면 python에 그 결과를 리턴하거나 list또는OrderedDict


그것은 너무 불행하다
JPG

내가 얻을 수 OrderedDict없는,dict
user66081

1

인스턴스를 직렬화 할 수없는 것처럼 보이지만 하나의 객체의 QuerySet을 직렬화해야합니다.

from django.core import serializers
from models import *

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

svndjango 릴리스가 부족 하므로 이전 버전이 아닐 수도 있습니다.


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

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

나는 나의 인스턴스를 받아 들인다

{ 'field1': value, "field2": value, ....}와 같은 것을 반환합니다.


이 끊어집니다 :TypeError: <django.db.models.base.ModelState object at 0x7f2b3bf62310> is not JSON serializable
훌리오 마린

1

이 방법은 어떻습니까 :

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

원하지 않는 것을 제외하십시오.


0

이 모든 대답은 내가 프레임 워크에서 기대할 수있는 것, 가장 간단한 방법과 비교하여 약간 해킹 적이었습니다.

rep = YourSerializerClass().to_representation(your_instance)
json.dumps(rep)

이것은 사용자가 정의한 필드와 연관 등을 고려하여 Serializer를 직접 사용합니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.