当前位置: 首页 > 知识库问答 >
问题:

将Django模型对象转换为dict,所有字段保持不变

薛淳
2023-03-14

如何将一个django模型对象转换为一个包含所有字段的判决?所有理想情况下包括外键和字段可编辑=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:将整个模型对象集转换为单个字典

如何将Django模型对象转换为字典,并且仍然保留它们的外键?

共有3个答案

南宫嘉
2023-03-14

只要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,
   }
梁丘柏
2023-03-14

我找到了一个简洁的解决方案来获得结果:

假设您有一个模型对象o

只要打电话:

type(o).objects.filter(pk=o.pk).values().first()
祁绪
2023-03-14

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

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\u-key被错误命名,并且它有两个多余的东西。

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}

这比标准的模型到dict调用更糟糕。

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}

这与实例的输出相同__dict__但不包含额外字段<代码>外键id仍然错误,多对多仍然缺失。

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

虽然这是最复杂的选项,但调用来指定(实例)可以准确地给出所需的结果:

{'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 Rest框架的ModelSerializer允许您从模型自动构建序列化程序。

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")

调用odel.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模型对象及其所有字段转换为字典?理想情况下,所有内容都包含带有的外键和字段。 让我详细说明。假设我有一个类似以下的Django模型: 在终端中,我已执行以下操作: 我想将其转换为以下字典: 问题答案: 有多种方法可以将实例转换为字典,并具有不同程度的转角案例处理和接近所需结果的程度。 1。 instance.dict 哪个返回 到目前为止,这是最简单的方法,但是缺少,

  • 我是Django的初学者。我需要将模型实例转换为类似于Model.objects的字典。值,与关系字段。所以我写了一个小函数来实现这一点: 所以,我可以这样使用它: 你能提出更好的解决方案吗?谢谢!附言:对不起我的英语。

  • 问题内容: 如果你是从Google来这里寻找模型的人,请跳过我的问题,然后跳到第一个答案。我的问题只会使你感到困惑。 在Django中,有没有一种很好的方法可以将整个模型对象集合到一个字典中?我的意思是,像这样: …结果是字典,键/值对由模型中的记录组成?还有其他人认为这对他们有用吗? 谢谢。 我只想添加的 更新 是,我的最终目标是能够在模板内进行简单的变量查找。就像是: 结果为DictModel

  • 问题内容: 我正在尝试使用Django中的ValuesQuerySet功能将查询返回的字段数限制为仅需要的字段数。我想将此数据集序列化为JSON对象。但是,Django不断抛出错误。下面包含了我的代码和收到的错误: 错误: 谢谢 ! 问题答案: 尝试使用QuerySet 通过方法对值列表中的字段进行子集设置:

  • 首先,我像这样扩展抽象用户: 然后参考如下其他模型: 这是形式: 这是视图: 我的问题是: > < li> 如何显示全名字段 以及如何通过应用程序数据的视图将这些字段保存到MyModel模型中的成员字段中? 更新 我更新了AbstractUser模型,因为我忘记添加first_name

  • 问题内容: 我的模特: 我想同时保存并保存在该模型中: 我知道这是错误的,但是我敢肯定,你会明白我的意思。你会怎么做? 问题答案: 你不能从未保存的对象创建m2m关系。如果有pk,请尝试以下操作: 更新:阅读了saverio的答案后,我决定对这个问题进行更深入的研究。这是我的发现。 这是我最初的建议。它可以工作,但不是最佳选择。(注意:我使用的是和而不是s和,但你明白了。) 它总共产生7个查询: