Có nhiều cách để chuyển đổi một thể hiện thành một từ điển, với mức độ xử lý tình huống góc khác nhau và sự gần gũi với kết quả mong muốn.
1. instance.__dict__
instance.__dict__
trả về
{'_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}
Điều này cho đến nay là đơn giản nhất, nhưng bị thiếu many_to_many
, foreign_key
được đặt tên sai, và nó có hai điều bổ sung không mong muốn trong đó.
2. model_to_dict
from django.forms.models import model_to_dict
model_to_dict(instance)
trả về
{'foreign_key': 2,
'id': 1,
'many_to_many': [<OtherModel: OtherModel object>],
'normal_value': 1}
Đây là người duy nhất có many_to_many
, nhưng thiếu các trường không thể chỉnh sửa.
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])
trả về
{'foreign_key': 2, 'id': 1, 'normal_value': 1}
Điều này là hoàn toàn tồi tệ hơn so với model_to_dict
lời mời tiêu chuẩn .
4. query_set.values()
SomeModel.objects.filter(id=instance.id).values()[0]
trả về
{'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}
Đây là đầu ra tương tự instance.__dict__
nhưng không có các trường bổ sung.
foreign_key_id
vẫn còn sai và many_to_many
vẫn còn thiếu
5. Chức năng tùy chỉnh
Mã cho django model_to_dict
đã có hầu hết các câu trả lời. Nó loại bỏ rõ ràng các trường không thể chỉnh sửa, do đó, việc xóa kiểm tra và nhận id của khóa ngoại đối với nhiều trường dẫn đến mã sau đây hoạt động như mong muốn:
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
Mặc dù đây là tùy chọn phức tạp nhất, việc gọi to_dict(instance)
cho chúng tôi chính xác kết quả mong muốn:
{'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. Sử dụng nối tiếp
ModelSerialzer của Django Rest Framework cho phép bạn tự động xây dựng bộ nối tiếp từ một mô hình.
from rest_framework import serializers
class SomeModelSerializer(serializers.ModelSerializer):
class Meta:
model = SomeModel
fields = "__all__"
SomeModelSerializer(instance).data
trả lại
{'auto_now_add': '2018-12-20T21:34:29.494827Z',
'foreign_key': 2,
'id': 1,
'many_to_many': [2],
'normal_value': 1,
'readonly_value': 2}
Điều này gần như tốt như hàm tùy chỉnh, nhưng auto_now_add là một chuỗi thay vì một đối tượng datetime.
Vòng thưởng: in mô hình tốt hơn
Nếu bạn muốn một mô hình django có màn hình dòng lệnh python tốt hơn, hãy tạo các mô hình con của bạn như sau:
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
Vì vậy, ví dụ, nếu chúng ta định nghĩa các mô hình của mình như sau:
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")
Gọi SomeModel.objects.first()
ngay bây giờ cho đầu ra như thế này:
{'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
và xử lý nó theo cách bạn muốn.