Django Model 객체를 변환하여 모든 필드를 그대로 유지하십시오.


257

Django Model 객체를 모든 필드 가있는 dict로 어떻게 변환 합니까? 모두 이상적으로로 외래 키와 필드를 포함 editable=False합니다.

자세히 설명하겠습니다. 다음과 같은 장고 모델이 있다고 가정 해 봅시다.

from django.db import models

class OtherModel(models.Model): pass

class SomeModel(models.Model):
    normal_value = models.IntegerField()
    readonly_value = models.IntegerField(editable=False)
    auto_now_add = models.DateTimeField(auto_now_add=True)
    foreign_key = models.ForeignKey(OtherModel, related_name="ref1")
    many_to_many = models.ManyToManyField(OtherModel, related_name="ref2")

터미널에서 다음을 수행했습니다.

other_model = OtherModel()
other_model.save()
instance = SomeModel()
instance.normal_value = 1
instance.readonly_value = 2
instance.foreign_key = other_model
instance.save()
instance.many_to_many.add(other_model)
instance.save()

이것을 다음 사전으로 변환하고 싶습니다.

{'auto_now_add': datetime.datetime(2015, 3, 16, 21, 34, 14, 926738, tzinfo=<UTC>),
 'foreign_key': 1,
 'id': 1,
 'many_to_many': [1],
 'normal_value': 1,
 'readonly_value': 2}

불만족스러운 답변이있는 질문 :

Django : 모델 객체 전체를 단일 사전으로 변환

Django Model 객체를 사전으로 바꾸고 외래 키를 어떻게 가질 수 있습니까?


1
호출 된 메소드를 선언하고 to_dict원하는 방식으로 처리 할 수 ​​있습니다.
karthikr

@karthikr 예, 가능합니다. 문제는 그러한 방법을 만드는 방법입니다. 모델의 모든 필드에서 사전을 수동으로 구성하는 것은 적합하지 않습니다.
Zags

Django Rest Framework, Tastypie 또는 Piston과 같은 기존 ReST 라이브러리를 활용하여 장고 모델 인스턴스를 직렬화를 위해 프리미티브로 변환하는 메커니즘을 제공합니다. 더 궁금한 점이 있으면 코드를 살펴볼 수 있지만 대부분 모델의 _meta정의를 통해 모델과 관련된 필드를 찾고 인스턴스에서 해당 값을 검색합니다.
Kevin Stone

답변:


523

다양한 수준의 코너 케이스 처리 및 원하는 결과와의 근접성을 통해 인스턴스를 사전으로 변환하는 방법에는 여러 가지가 있습니다.


1. instance.__dict__

instance.__dict__

어떤 반환

{'_foreign_key_cache': <OtherModel: OtherModel object>,
 '_state': <django.db.models.base.ModelState at 0x7ff0993f6908>,
 'auto_now_add': datetime.datetime(2018, 12, 20, 21, 34, 29, 494827, tzinfo=<UTC>),
 'foreign_key_id': 2,
 'id': 1,
 'normal_value': 1,
 'readonly_value': 2}

이것은 지금까지 가장 단순하지만 누락 many_to_many되어 foreign_key있고 이름이 잘못되어 있으며 원치 않는 두 가지 추가 항목이 있습니다.


2. model_to_dict

from django.forms.models import model_to_dict
model_to_dict(instance)

어떤 반환

{'foreign_key': 2,
 'id': 1,
 'many_to_many': [<OtherModel: OtherModel object>],
 'normal_value': 1}

이 (가)있는 유일한 항목 many_to_many이지만 편집 할 수없는 필드가 없습니다.


삼. model_to_dict(..., fields=...)

from django.forms.models import model_to_dict
model_to_dict(instance, fields=[field.name for field in instance._meta.fields])

어떤 반환

{'foreign_key': 2, 'id': 1, 'normal_value': 1}

이것은 표준 model_to_dict호출 보다 엄격히 나쁩니다 .


4. query_set.values()

SomeModel.objects.filter(id=instance.id).values()[0]

어떤 반환

{'auto_now_add': datetime.datetime(2018, 12, 20, 21, 34, 29, 494827, tzinfo=<UTC>),
 'foreign_key_id': 2,
 'id': 1,
 'normal_value': 1,
 'readonly_value': 2}

이는 instance.__dict__추가 필드가없는 출력과 동일 합니다. foreign_key_id여전히 잘못되어 many_to_many여전히 누락되었습니다.


5. 사용자 정의 기능

django의 코드 model_to_dict는 대부분의 대답을했습니다. 편집 할 수없는 필드를 명시 적으로 제거 했으므로 해당 검사를 제거하고 많은 필드에서 외래 키의 ID를 얻으면 다음 코드가 원하는대로 작동합니다.

from itertools import chain

def to_dict(instance):
    opts = instance._meta
    data = {}
    for f in chain(opts.concrete_fields, opts.private_fields):
        data[f.name] = f.value_from_object(instance)
    for f in opts.many_to_many:
        data[f.name] = [i.id for i in f.value_from_object(instance)]
    return data

이것이 가장 복잡한 옵션이지만 호출 to_dict(instance)하면 원하는 결과를 정확하게 얻을 수 있습니다.

{'auto_now_add': datetime.datetime(2018, 12, 20, 21, 34, 29, 494827, tzinfo=<UTC>),
 'foreign_key': 2,
 'id': 1,
 'many_to_many': [2],
 'normal_value': 1,
 'readonly_value': 2}

6. 시리얼 라이저 사용

Django Rest Framework 의 ModelSerialzer를 사용하면 모델에서 자동으로 시리얼 라이저를 작성할 수 있습니다.

from rest_framework import serializers
class SomeModelSerializer(serializers.ModelSerializer):
    class Meta:
        model = SomeModel
        fields = "__all__"

SomeModelSerializer(instance).data

보고

{'auto_now_add': '2018-12-20T21:34:29.494827Z',
 'foreign_key': 2,
 'id': 1,
 'many_to_many': [2],
 'normal_value': 1,
 'readonly_value': 2}

이것은 거의 사용자 정의 함수만큼 좋지만 auto_now_add는 datetime 객체 대신 문자열입니다.


보너스 라운드 : 더 나은 모델 인쇄

더 나은 파이썬 커맨드 라인 디스플레이를 가진 장고 모델을 원한다면, 모델이 다음과 같은 자식 클래스를 갖도록하십시오 :

from django.db import models
from itertools import chain

class PrintableModel(models.Model):
    def __repr__(self):
        return str(self.to_dict())

    def to_dict(instance):
        opts = instance._meta
        data = {}
        for f in chain(opts.concrete_fields, opts.private_fields):
            data[f.name] = f.value_from_object(instance)
        for f in opts.many_to_many:
            data[f.name] = [i.id for i in f.value_from_object(instance)]
        return data

    class Meta:
        abstract = True

예를 들어 모델을 다음과 같이 정의하면

class OtherModel(PrintableModel): pass

class SomeModel(PrintableModel):
    normal_value = models.IntegerField()
    readonly_value = models.IntegerField(editable=False)
    auto_now_add = models.DateTimeField(auto_now_add=True)
    foreign_key = models.ForeignKey(OtherModel, related_name="ref1")
    many_to_many = models.ManyToManyField(OtherModel, related_name="ref2")

호출 SomeModel.objects.first()하면 다음과 같은 출력이 나타납니다.

{'auto_now_add': datetime.datetime(2018, 12, 20, 21, 34, 29, 494827, tzinfo=<UTC>),
 'foreign_key': 2,
 'id': 1,
 'many_to_many': [2],
 'normal_value': 1,
 'readonly_value': 2}

2
이 답변에 감사드립니다! isinstance솔루션 # 5 (및 보너스) 의 테스트를로 변경할 수 있습니다 if f.many_to_many.
dhobbs

1
@dhobbs 나는 장고의 떨어져 그 코드를 모델링 model_to_dict하는 용도 코드 isinstance. 왜 그들이이 선택을했는지 모르겠지만, 그 이유가있을 수 있습니다 (예 : many_to_many이후 버전에서 소개 될 자산)
Zags

또한 @property필드 를 반환 합니까?
angrysumit

1
이 방법이 주석이 달린 / ​​집계 된 필드를 어떻게 처리하는지 궁금합니다.
mehmet

내가하는 일은 get_FOO_display를 확인하고 실제로있을 수있는 값 대신 해당 값을 반환하는 것입니다.
Bobort

9

결과를 얻을 수있는 깔끔한 솔루션을 찾았습니다.

모델 객체가 있다고 가정하십시오 o.

그냥 전화하십시오 :

type(o).objects.filter(pk=o.pk).values().first()

10
이것은 제 답변에서 옵션 # 4입니다
Zags

7

@ Zags 솔루션은 화려했습니다!

그러나 JSON을 친화적으로 만들기 위해 날짜 필드에 대한 조건을 추가하려고합니다.

보너스 라운드

더 나은 파이썬 명령 줄 표시를 가진 장고 모델을 원한다면 모델에 다음과 같은 자식 클래스를 작성하십시오.

from django.db import models
from django.db.models.fields.related import ManyToManyField

class PrintableModel(models.Model):
    def __repr__(self):
        return str(self.to_dict())

    def to_dict(self):
        opts = self._meta
        data = {}
        for f in opts.concrete_fields + opts.many_to_many:
            if isinstance(f, ManyToManyField):
                if self.pk is None:
                    data[f.name] = []
                else:
                    data[f.name] = list(f.value_from_object(self).values_list('pk', flat=True))
            elif isinstance(f, DateTimeField):
                if f.value_from_object(self) is not None:
                    data[f.name] = f.value_from_object(self).timestamp()
            else:
                data[f.name] = None
            else:
                data[f.name] = f.value_from_object(self)
        return data

    class Meta:
        abstract = True

예를 들어 모델을 다음과 같이 정의하면

class OtherModel(PrintableModel): pass

class SomeModel(PrintableModel):
    value = models.IntegerField()
    value2 = models.IntegerField(editable=False)
    created = models.DateTimeField(auto_now_add=True)
    reference1 = models.ForeignKey(OtherModel, related_name="ref1")
    reference2 = models.ManyToManyField(OtherModel, related_name="ref2")

호출 SomeModel.objects.first()하면 다음과 같은 출력이 나타납니다.

{'created': 1426552454.926738,
'value': 1, 'value2': 2, 'reference1': 1, u'id': 1, 'reference2': [1]}

JSON으로 변환하거나 JSON으로 변환하려면 Django Rest Framework를 보거나 다음과 같이 사용해야합니다. stackoverflow.com/a/22238613/2800876
Zags

확실한! 그러나이 작은 코드 변경으로 인해 많은 편의가 추가되었습니다!
Diego Freitas Coelho

4

가장 간단한 방법,

  1. 쿼리가 Model.Objects.get () 인 경우 :

    get ()은 단일 인스턴스를 반환하므로 직접 사용할 수 있습니다 __dict__ 인스턴스에서

    model_dict = Model.Objects.get().__dict__

  2. 에 대한 필터 () / 모든 () :

    all () / filter () 는 인스턴스 목록을 반환하므로 values()객체 목록을 얻는 데 사용할 수 있습니다 .

    model_values ​​= Model.Objects.all (). values ​​()


4

그냥 vars(obj)객체의 전체 값을 나타냅니다.

>>> obj_attrs = vars(obj)
>>> obj_attrs
 {'_file_data_cache': <FileData: Data>,
  '_state': <django.db.models.base.ModelState at 0x7f5c6733bad0>,
  'aggregator_id': 24,
  'amount': 5.0,
  'biller_id': 23,
  'datetime': datetime.datetime(2018, 1, 31, 18, 43, 58, 933277, tzinfo=<UTC>),
  'file_data_id': 797719,
 }

이것을 추가 할 수도 있습니다

>>> keys = obj_attrs.keys()
>>> temp = [obj_attrs.pop(key) if key.startswith('_') else None for key in keys]
>>> del temp
>>> obj_attrs
   {
    'aggregator_id': 24,
    'amount': 5.0,
    'biller_id': 23,
    'datetime': datetime.datetime(2018, 1, 31, 18, 43, 58, 933277, tzinfo=<UTC>),
    'file_data_id': 797719,
   }

3

최신 정보

@zags에 의해 게시 된 새로운 집계 답변은 내 것보다 완벽하고 우아합니다. 대신 해당 답변을 참조하십시오.

실물

@karthiker가 제안한 것처럼 자신의 to_dict 메소드를 기꺼이 정의하려는 경우이 문제를 세트 문제로 요약합니다.

>>># Returns a set of all keys excluding editable = False keys
>>>dict = model_to_dict(instance)
>>>dict

{u'id': 1L, 'reference1': 1L, 'reference2': [1L], 'value': 1}


>>># Returns a set of editable = False keys, misnamed foreign keys, and normal keys
>>>otherDict = SomeModel.objects.filter(id=instance.id).values()[0]
>>>otherDict

{'created': datetime.datetime(2014, 2, 21, 4, 38, 51, tzinfo=<UTC>),
 u'id': 1L,
 'reference1_id': 1L,
 'value': 1L,
 'value2': 2L}

otherDict 에서 잘못 레이블 된 외래 키를 제거해야합니다 .

이를 위해 밑줄이있는 항목을 제외한 모든 항목이 포함 된 새 사전을 만드는 루프를 사용할 수 있습니다. 또는 시간을 절약하기 위해 사전을 후드 아래에 설정 하기 때문에 원래 dict에 추가 할 수 있습니다 .

>>>for item in otherDict.items():
...    if "_" not in item[0]:
...            dict.update({item[0]:item[1]})
...
>>>

따라서 우리는 다음과 같은 구술을 남겼습니다 .

>>>dict
{'created': datetime.datetime(2014, 2, 21, 4, 38, 51, tzinfo=<UTC>),
 u'id': 1L,
 'reference1': 1L,
 'reference2': [1L],
 'value': 1,
 'value2': 2L}

그리고 당신은 그것을 돌려줍니다.

단점은 editable = false 필드 이름에 밑줄을 사용할 수 없습니다. 거꾸로, 이것은 사용자가 만든 필드에 밑줄이 포함되지 않은 모든 필드 집합에 적용됩니다.

이것이 최선의 방법은 아니지만보다 직접적인 방법을 찾을 때까지 임시 솔루션으로 작동 할 수 있습니다.

아래 예제의 경우 dict는 model_to_dict를 기반으로 구성되고 otherDict는 필터의 값 방법으로 구성됩니다. 모델 자체 에서이 작업을 수행했지만 기계가 다른 모델을 수락하도록 할 수는 없습니다.

>>> import datetime
>>> dict = {u'id': 1, 'reference1': 1, 'reference2': [1], 'value': 1}
>>> otherDict = {'created': datetime.datetime(2014, 2, 21, 4, 38, 51), u'id': 1, 'reference1_id': 1, 'value': 1, 'value2': 2}
>>> for item in otherDict.items():
...     if "_" not in item[0]:
...             dict.update({item[0]:item[1]})
...
>>> dict
{'reference1': 1, 'created': datetime.datetime(2014, 2, 21, 4, 38, 51), 'value2': 2, 'value': 1, 'id': 1, 'reference2': [1]}
>>>

그것은 당신의 질문에 대한 대답의 거친 야구장에 당신을 두어야합니다.


1
re여기서 사용하려는 것이 확실하지 않습니다 . 밑줄이있는 키를 걸러 내려면 올바른 코드 나 올바른 동작이 아닙니다. 데이터베이스의 re.match("_", "reference1_id")반환 None및 합법적 인 열에는 이름에 밑줄이있을 수 있습니다.
저쪽으로 네요

re.match ( "는 _", "reference1_id") 않습니다 반환 없음, 그것은 있었어야 : re.match ( ".. * _ *", "reference1_id")
가젯

나쁜 예를 제거하고 더 좋은 예를 포함시키기 위해 변경했습니다. 또한 이것이 모든 모델의 하위 집합에 대한 임시 솔루션이 될 것이라고 표현하기 위해 몇 가지 사항을 변경했습니다. 해당 editable=false분야에 밑줄이있는 모델에 대해 어떻게해야할지 모르겠습니다 . 더 많은 정식 솔루션이 제공 될 때까지 작업 할 수있는 것을 제공하려고했습니다.
가제트

이 경우 "_" in string보다는 오히려 사용하십시오 re.
Zags

그렇습니다. 훨씬 쉬운 방법입니다. 이런 식으로 사용하지는 않았지만 지금은 완벽하게 이해됩니다. in대신 을 사용하도록 답변을 변경했습니다 re.
가제트

2

흥미로운 솔루션이 많이 있습니다. 내 솔루션은 dict comprehension으로 모델에 as_dict 메소드를 추가하는 것이 었습니다.

def as_dict(self):
    return dict((f.name, getattr(self, f.name)) for f in self._meta.fields)

또한이 솔루션을 쿼리에 대한 목록 이해와 함께 사용하면 모델을 다른 라이브러리로 내보내려는 경우 훌륭한 솔루션이됩니다. 예를 들어, 팬더 데이터 프레임에 모델을 덤프하는 경우 :

pandas_awesomeness = pd.DataFrame([m.as_dict() for m in SomeModel.objects.all()])

1
이것은 문자열이나 정수와 같은 값 필드에는 잘 작동하지만 외래 키에는 많은 문제가 있고 많은 필드에는 더 많은 문제가 있습니다.
Zags

아주 좋은 지적입니다! 특히 많은 사람들에게. 이러한 경우를 적절하게 처리하기 위해 일부 조건을 설정 하거나이 솔루션을 간단한 모델로 제한하려고합니다. 감사.
t1m0

1

(설명을 의미하지 않았다)

좋아, 실제로 그런 식으로 유형에 의존하지는 않습니다. 나는 여기서 원래의 질문을 잘못 이해했을 수도 있으므로 그러한 경우라면 용서하십시오. serliazers.py를 만들면 메타 클래스가있는 클래스가 만들어집니다.

Class MyModelSerializer(serializers.ModelSerializer):
    class Meta:
        model = modelName
        fields =('csv','of','fields')

그런 다음 뷰 클래스에서 데이터를 가져 오면 다음을 수행 할 수 있습니다.

model_data - Model.objects.filter(...)
serializer = MyModelSerializer(model_data, many=True)
return Response({'data': serilaizer.data}, status=status.HTTP_200_OK)

그것은 내가 많은 장소에 가지고있는 것과 거의 같으며 JSONRenderer를 통해 멋진 JSON을 반환합니다.

내가 말했듯이 이것은 DjangoRestFramework의 예의이므로 그렇게 볼 가치가 있습니다.


1

더 쉬운 방법은 pprint기본 Python에있는을 사용 하는 것입니다.

import pprint
item = MyDjangoModel.objects.get(name = 'foo')
pprint.pprint(item.__dict__, indent = 4)

결과는 비슷해 보이지만 json.dumps(..., indent = 4)모델 인스턴스에 임베드 될 수있는 이상한 데이터 유형 (예 : ModelStateUUID 등)을 .

Python 3.7에서 테스트


0

아마도 이것은 당신을 도울 것입니다. 이것은 많은 대대적 인 포기를 가리지 않지만 json 형식으로 모델을 보내려고 할 때 매우 편리합니다.

def serial_model(modelobj):
  opts = modelobj._meta.fields
  modeldict = model_to_dict(modelobj)
  for m in opts:
    if m.is_relation:
        foreignkey = getattr(modelobj, m.name)
        if foreignkey:
            try:
                modeldict[m.name] = serial_model(foreignkey)
            except:
                pass
  return modeldict

0

지금까지 본 최고의 솔루션.

django.db.models.Model 인스턴스 및 모든 관련 ForeignKey, ManyToManyField 및 @Property 함수 필드를 dict로 변환하십시오.

"""
Convert django.db.models.Model instance and all related ForeignKey, ManyToManyField and @property function fields into dict.
Usage:
    class MyDjangoModel(... PrintableModel):
        to_dict_fields = (...)
        to_dict_exclude = (...)
        ...
    a_dict = [inst.to_dict(fields=..., exclude=...) for inst in MyDjangoModel.objects.all()]
"""
import typing

import django.core.exceptions
import django.db.models
import django.forms.models


def get_decorators_dir(cls, exclude: typing.Optional[set]=None) -> set:
    """
    Ref: /programming/4930414/how-can-i-introspect-properties-and-model-fields-in-django
    :param exclude: set or None
    :param cls:
    :return: a set of decorators
    """
    default_exclude = {"pk", "objects"}
    if not exclude:
        exclude = default_exclude
    else:
        exclude = exclude.union(default_exclude)

    return set([name for name in dir(cls) if name not in exclude and isinstance(getattr(cls, name), property)])


class PrintableModel(django.db.models.Model):

    class Meta:
        abstract = True

    def __repr__(self):
        return str(self.to_dict())

    def to_dict(self, fields: typing.Optional[typing.Iterable]=None, exclude: typing.Optional[typing.Iterable]=None):
        opts = self._meta
        data = {}

        # support fields filters and excludes
        if not fields:
            fields = set()
        else:
            fields = set(fields)
        default_fields = getattr(self, "to_dict_fields", set())
        fields = fields.union(default_fields)

        if not exclude:
            exclude = set()
        else:
            exclude = set(exclude)
        default_exclude = getattr(self, "to_dict_exclude", set())
        exclude = exclude.union(default_exclude)

        # support syntax "field__childField__..."
        self_fields = set()
        child_fields = dict()
        if fields:
            for i in fields:
                splits = i.split("__")
                if len(splits) == 1:
                    self_fields.add(splits[0])
                else:
                    self_fields.add(splits[0])

                    field_name = splits[0]
                    child_fields.setdefault(field_name, set())
                    child_fields[field_name].add("__".join(splits[1:]))

        self_exclude = set()
        child_exclude = dict()
        if exclude:
            for i in exclude:
                splits = i.split("__")
                if len(splits) == 1:
                    self_exclude.add(splits[0])
                else:
                    field_name = splits[0]
                    if field_name not in child_exclude:
                        child_exclude[field_name] = set()
                    child_exclude[field_name].add("__".join(splits[1:]))

        for f in opts.concrete_fields + opts.many_to_many:
            if self_fields and f.name not in self_fields:
                continue
            if self_exclude and f.name in self_exclude:
                continue

            if isinstance(f, django.db.models.ManyToManyField):
                if self.pk is None:
                    data[f.name] = []
                else:
                    result = []
                    m2m_inst = f.value_from_object(self)
                    for obj in m2m_inst:
                        if isinstance(PrintableModel, obj) and hasattr(obj, "to_dict"):
                            d = obj.to_dict(
                                fields=child_fields.get(f.name),
                                exclude=child_exclude.get(f.name),
                            )
                        else:
                            d = django.forms.models.model_to_dict(
                                obj,
                                fields=child_fields.get(f.name),
                                exclude=child_exclude.get(f.name)
                            )
                        result.append(d)
                    data[f.name] = result
            elif isinstance(f, django.db.models.ForeignKey):
                if self.pk is None:
                    data[f.name] = []
                else:
                    data[f.name] = None
                    try:
                        foreign_inst = getattr(self, f.name)
                    except django.core.exceptions.ObjectDoesNotExist:
                        pass
                    else:
                        if isinstance(foreign_inst, PrintableModel) and hasattr(foreign_inst, "to_dict"):
                            data[f.name] = foreign_inst.to_dict(
                                fields=child_fields.get(f.name),
                                exclude=child_exclude.get(f.name)
                            )
                        elif foreign_inst is not None:
                            data[f.name] = django.forms.models.model_to_dict(
                                foreign_inst,
                                fields=child_fields.get(f.name),
                                exclude=child_exclude.get(f.name),
                            )

            elif isinstance(f, (django.db.models.DateTimeField, django.db.models.DateField)):
                v = f.value_from_object(self)
                if v is not None:
                    data[f.name] = v.isoformat()
                else:
                    data[f.name] = None
            else:
                data[f.name] = f.value_from_object(self)

        # support @property decorator functions
        decorator_names = get_decorators_dir(self.__class__)
        for name in decorator_names:
            if self_fields and name not in self_fields:
                continue
            if self_exclude and name in self_exclude:
                continue

            value = getattr(self, name)
            if isinstance(value, PrintableModel) and hasattr(value, "to_dict"):
                data[name] = value.to_dict(
                    fields=child_fields.get(name),
                    exclude=child_exclude.get(name)
                )
            elif hasattr(value, "_meta"):
                # make sure it is a instance of django.db.models.fields.Field
                data[name] = django.forms.models.model_to_dict(
                    value,
                    fields=child_fields.get(name),
                    exclude=child_exclude.get(name),
                )
            elif isinstance(value, (set, )):
                data[name] = list(value)
            else:
                data[name] = value

        return data

https://gist.github.com/shuge/f543dc2094a3183f69488df2bfb51a52


0

@zags의 대답은 포괄적이며 충분해야 하지만 # 5 방법 (최고의 IMO)이 오류를 발생시켜 도우미 기능을 향상 시켰습니다.

영업 이익은 변환 요청으로 many_to_many기본 키가 아닌 객체의 목록의 목록에 필드를 반환 값이 이제 JSON의 직렬화, 그래서 나는 기능을 강화 - 변환하여 datetime, 물체 strmany_to_manyID의 목록에 개체를.

import datetime

def ModelToDict(instance):
    '''
    Returns a dictionary object containing complete field-value pairs of the given instance

    Convertion rules:

        datetime.date --> str
        many_to_many --> list of id's

    '''

    concrete_fields = instance._meta.concrete_fields
    m2m_fields = instance._meta.many_to_many
    data = {}

    for field in concrete_fields:
        key = field.name
        value = field.value_from_object(instance)
        if type(value) == datetime.datetime:
            value = str(field.value_from_object(instance))
        data[key] = value

    for field in m2m_fields:
        key = field.name
        value = field.value_from_object(instance)
        data[key] = [rel.id for rel in value]

    return data

당신이 얻는 오류는 무엇입니까? 답변을 업데이트하게되어 기쁩니다
Zags

현재를 통해 루프의 기능 concrete_fieldsm2m_fields가정하므로, 동일한 모양 m2m_fields루프 것은 여기에 잘못된 구현을 가지고있다.
다니엘 힘멜 슈타인

@ Zags 오류는 AttributeError: 'list' object has no attribute 'values_list' 그 이유를 찾을 수없는 것입니다. Django 2.1.1을 사용하는 메신저
Armin Hemati Nik

@ daniel-himmelstein 지적 해 주셔서 감사합니다. 코드를 수정했습니다. 동일한 루프의 이유는 내 로컬 코드에서 다른 작업을 수행했기 때문에 발생했으며 SO 응답에 맞게 최적화하는 것을 잊었습니다.
Armin Hemati Nik

@ArminHemati Django는의 구현을 변경했으며 field.value_from_object그 결과로 의 구현을 변경했습니다 model_to_dict. 이것을 반영하기 위해 답변의 섹션 5를 업데이트했습니다.
Zags
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.