다양한 수준의 코너 케이스 처리 및 원하는 결과와의 근접성을 통해 인스턴스를 사전으로 변환하는 방법에는 여러 가지가 있습니다.
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}
to_dict
원하는 방식으로 처리 할 수 있습니다.