从 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 rest 框架:从序列化器 validate() 方法设置字段级错误
如何为 Django Model PK 使用自定义 Oracle 序列?