如何将django Model对象转换为包含所有字段的dict ?理想情况下,所有字段都包含外键和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}
回答不满意的问题:
Django:将整个Model对象集转换为单个字典
如何将Django Model对象转换为字典,同时还保留外键?
@Zags的解决方案太棒了!
不过,为了使它对JSON友好,我要为datefields添加一个条件。
奖金轮
如果你想要一个更好的python命令行显示的django模型,让你的models子类如下:
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")
调用sommodel .objects.first()现在给出如下输出:
{'created': 1426552454.926738,
'value': 1, 'value2': 2, 'reference1': 1, u'id': 1, 'reference2': [1]}
只有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,
}
将模型转换为字典并保留所有的外键模型关系。我使用了以下方法:
无详细名称
from django.forms.models import model_to_dict
instance = MyModel.objects.get(pk=1) # EXAMPLE
instance_dict = {key: getattr(instance, key) for key in model_to_dict(instance).keys()}
输出
{'foreign_key': [<OtherModel: OtherModel object>],
'id': 1,
'many_to_many': [<OtherModel: OtherModel object>],
'normal_value': 1}
如果你想在模板中为外键关系显示__str__()值,这可能很有用。
将关键字参数fields=和exclude=包含到model_to_dict(instance,[…])中,使您可以过滤特定的字段。
详细名称
from django.forms.models import model_to_dict
instance = MyModel.objects.get(pk=1) # EXAMPLE
instance_dict = {instance._meta.get_field(key).verbose_name if hasattr(instance._meta.get_field(key), 'verbose_name') else key: getattr(instance, key) for key in model_to_dict(instance).keys()}
示例输出(如果给定示例有详细的名称)
{'Other Model:': [<OtherModel: OtherModel object>],
'id': 1,
'My Other Model:': [<OtherModel: OtherModel object>],
'Normal Value:': 1}
(不是故意的)
好吧,它并不依赖于类型。我可能误解了最初的问题,所以如果是这样的话请原谅我。如果你创建serliazers.py,那么你在里面创建了有元类的类。
Class MyModelSerializer(serializers.ModelSerializer):
class Meta:
model = modelName
fields =('csv','of','fields')
然后,当你在视图类中获得数据时,你可以:
model_data - Model.objects.filter(...)
serializer = MyModelSerializer(model_data, many=True)
return Response({'data': serilaizer.data}, status=status.HTTP_200_OK)
这就是我在很多地方所拥有的,它通过JSONRenderer返回漂亮的JSON。
正如我所说,这是由DjangoRestFramework提供的,所以值得研究一下。