将Django模型对象转换为所有字段均完整的dict

如何将Django模型对象及其所有字段转换为字典?理想情况下,所有内容都包含带有的外键和字段editable=False

让我详细说明。假设我有一个类似以下的Django模型:

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}

回答:

有多种方法可以将实例转换为字典,并具有不同程度的转角案例处理和接近所需结果的程度。

1。 instance.

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_manyforeign_key被错误命名,并且其中有两个多余的多余内容。

2。

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,但缺少不可编辑的字段。

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。

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

returns

{'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对象。

奖金回合:更好的模型打印

如果你想要具有更好的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}

以上是 将Django模型对象转换为所有字段均完整的dict 的全部内容, 来源链接: utcz.com/qa/430180.html

回到顶部