มีหลายวิธีในการแปลงอินสแตนซ์เป็นพจนานุกรมโดยมีองศาการจัดการตัวพิมพ์มุมและการใกล้เคียงกับผลลัพธ์ที่ต้องการ
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
ฟิลด์แต่ไม่มีฟิลด์ที่แก้ไขไม่ได้
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. ฟังก์ชั่นที่กำหนดเอง
รหัสสำหรับ django's model_to_dict
มีคำตอบส่วนใหญ่ มันลบเขตข้อมูลที่ไม่สามารถแก้ไขได้อย่างชัดเจนดังนั้นการลบการตรวจสอบและการรับรหัสต่างประเทศสำหรับเขตข้อมูลจำนวนมากไปยังเขตพื้นที่ต่าง ๆ ส่งผลให้รหัสต่อไปนี้ซึ่งทำงานตามที่ต้องการ:
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. ใช้ Serializers
ModelSerialzer ของDjango Rest Frameworkอนุญาตให้คุณสร้าง serializer โดยอัตโนมัติจากรุ่น
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
รอบโบนัส: การพิมพ์แบบที่ดีขึ้น
หากคุณต้องการรุ่น django ที่มีการแสดงบรรทัดคำสั่งของ python ที่ดีกว่าให้รุ่นของคุณเป็นคลาสย่อยดังต่อไปนี้:
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
และจัดการในแบบที่คุณต้องการ