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. 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}
๋ต๋ณ
๊ฒฐ๊ณผ๋ฅผ ์ป์ ์์๋ ๊น๋ํ ์๋ฃจ์ ์ ์ฐพ์์ต๋๋ค.
๋ชจ๋ธ ๊ฐ์ฒด๊ฐ ์๋ค๊ณ ๊ฐ์ ํ์ญ์์ค o
.
๊ทธ๋ฅ ์ ํํ์ญ์์ค :
type(o).objects.filter(pk=o.pk).values().first()
๋ต๋ณ
@ 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]}
๋ต๋ณ
๊ฐ์ฅ ๊ฐ๋จํ ๋ฐฉ๋ฒ,
-
์ฟผ๋ฆฌ๊ฐ Model.Objects.get () ์ธ ๊ฒฝ์ฐ :
get ()์ ๋จ์ผ ์ธ์คํด์ค๋ฅผ ๋ฐํํ๋ฏ๋ก ์ง์ ์ฌ์ฉํ ์ ์์ต๋๋ค
__dict__
์ธ์คํด์ค์์model_dict =
Model.Objects.get().__dict__
-
์ ๋ํ ํํฐ () / ๋ชจ๋ () :
all () / filter () ๋ ์ธ์คํด์ค ๋ชฉ๋ก์ ๋ฐํํ๋ฏ๋ก
values()
๊ฐ์ฒด ๋ชฉ๋ก์ ์ป๋ ๋ฐ ์ฌ์ฉํ ์ ์์ต๋๋ค .model_values โโ= Model.Objects.all (). values โโ()
๋ต๋ณ
๊ทธ๋ฅ 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,
}
๋ต๋ณ
์ต์ ์ ๋ณด
@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]}
>>>
๊ทธ๊ฒ์ ๋น์ ์ ์ง๋ฌธ์ ๋ํ ๋๋ต์ ๊ฑฐ์น ์ผ๊ตฌ์ฅ์ ๋น์ ์ ๋์ด์ผํฉ๋๋ค.
๋ต๋ณ
ํฅ๋ฏธ๋ก์ด ์๋ฃจ์ ์ด ๋ง์ด ์์ต๋๋ค. ๋ด ์๋ฃจ์ ์ 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()])