インスタンスをディクショナリに変換するには多くの方法があり、コーナーケースの処理の度合いや目的の結果への近さはさまざまです。
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つあります。
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
ですが、編集できないフィールドがありません。
3。 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.カスタム関数
ジャンゴのためのコード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は日時オブジェクトではなく文字列です。
ボーナスラウンド:より良いモデル印刷
より優れたpythonコマンドライン表示を持つdjangoモデルが必要な場合は、モデルに次の子クラスを持たせます。
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
それを希望どおりに処理できます。