从 django 序列化对象中删除 pk 字段

Posted

技术标签:

【中文标题】从 django 序列化对象中删除 pk 字段【英文标题】:Remove pk field from django serialized objects 【发布时间】:2010-12-09 14:16:58 【问题描述】:

我正在序列化一堆对象:

json = serializers.serialize("json", objects, fields=('name', 'country'))

我的字段列表中没有包含“pk”,但生成的 JSON 包含一个主键和每个序列化对象。我不希望我的 API 向公众公开主键。

没有修改输出 JSON,告诉serializers.serialze() 不包含主键的正确方法是什么?

【问题讨论】:

@Josh Reich 你最后做了什么?有一张票在谈论它@code.djangoproject.com/ticket/4656 我最终手动调用了 simplejson 【参考方案1】:

我们不会浪费时间尝试“清理”PK。当我们生成 JSON 记录时,PK 就在那里,用户可以根据需要忽略它。他们无法对这些信息做任何事情,所以它只是杂乱无章。

我们的 Web 服务界面均不允许任何人向我们提供 PK。我们在其他字段上进行 POST、PUT 和 DELETE 搜索,但不是 PK。

然而,html 始终显示 PK 的 URL。它可以让人们为页面添加书签。

【讨论】:

许多公司假定顺序主键中不包含任何信息。如果您已锁定访问控制,则无需担心,对吗?错误的。至少,显示顺序标识符为竞争对手跟踪您的增长提供了一种很好的方式。仅仅基于找到连续 ID 和销售增长估计,就有一个相当大的行业。 您可以通过使用 UUID 而不是顺序 ID 来解决您的问题,因此将它们公开不会为竞争对手提供任何信息。 还要考虑包含 pk & 模型时发送给每个用户的额外文本。这是可以非常清楚地节省的带宽(尤其是在将其发送给移动用户时)。【参考方案2】:

我最终通过使用底层simplejson 序列化程序“手动”实现我想要的来解决这个问题:

from django.utils import simplejson
json = simplejson.dumps( ['name': o.name,
                           'country': o.country for o in objects] )

打字多一点,但有效。

【讨论】:

如果您只想将一些数据转储到 json 并且不关心 FK,这是一个很好的解决方案。 @Josh 如果您在一个 API 中有 28 个方法使用 5 个模型,那么编码会更多。 我用过这个。但是当您在多个视图中使用它时会很麻烦。最好使用 Django 的序列化程序。最后一个答案有一个相关问题的链接,它解释了如何从它生成的对象中删除 pk 和 model 字段。【参考方案3】:

虽然这是一个老问题,但其他人可能会在 Google 搜索中提出这个问题。

不幸的是,django 序列化程序提供的自定义很少,就像您定义的那样。我的解决方案,如果您知道您将在您的项目中使用大量序列化,只需将 django 的序列化内容复制到我自己的项目并进行一些小的更改。这并不理想,但它可以完成工作。具体来说,要去掉pk,在start_object(self, obj)中有一行:

self.xml.startElement("object", 
        "pk"    : smart_unicode(obj._get_pk_val()),
        "model" : smart_unicode(obj._meta),
    )

删除“pk”行应该可以解决它。这是一个有点肮脏的 hack,因为如果他们稍后改进它,可能需要对您的视图进行一些更改,但对我来说,这是绕过限制的最简单方法。

希望这对某人有所帮助。

【讨论】:

【参考方案4】:

您也可以按照此处的说明覆盖 JSON 序列化程序:Override Django Object Serializer to get rid of specified model

from django.core.serializers.json import Serializer, DjangoJSONEncoder
from django.utils import simplejson

import logging

class MySerializer(Serializer):
    def end_serialization(self):
        cleaned_objects = []

        for obj in self.objects:
            del obj['pk']
            cleaned_objects.append(obj)

        simplejson.dump(cleaned_objects, self.stream, cls=DjangoJSONEncoder, **self.options)

【讨论】:

谢谢!这个问题的答案很有帮助!【参考方案5】:

丑陋(但有效)的方式:

data_tmp = data.split('')
#Gets all the data after fields
response = "["+data_tmp[2].replace("","",1)

【讨论】:

【参考方案6】:

乔希做了什么,但倒退了:

data = json.loads(json_string)

for d in data:
    del d['pk']
    del d['model']

data = json.dumps(data)

这样您以后在添加更多字段时不必担心更新代码。

【讨论】:

【参考方案7】:

我遇到了同样的问题,所以我创建了自己的Serializer,继承自 Django 的 Serializer。 我只想要字段的数据,所以我覆盖了方法get_dump_object,并添加了PK字段。

from django.core.serializers.json import Serializer


class JSONSerializer(Serializer):
    def get_dump_object(self, obj):
        self._current[obj._meta.pk.name] = obj._get_pk_val()
        return self._current

然后调用:

output = JSONSerializer().serialize(queryset)

【讨论】:

以上是关于从 django 序列化对象中删除 pk 字段的主要内容,如果未能解决你的问题,请参考以下文章

python Django Views - 如何将django对象数组序列化为平面JSON(排除模型,pk和fields节点)

Django序列化来自不同模型的字段

django rest 框架:从序列化器 validate() 方法设置字段级错误

如何为 Django Model PK 使用自定义 Oracle 序列?

无法在 Django Rest Framework 序列化程序的验证数据中获取非模型字段

如何从序列化器字段订购 django rest 框架查询集?