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

我正在序列化一堆对象:

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

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

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

【问题讨论】:

标签: django json serialization


【解决方案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)
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2011-03-17
          • 1970-01-01
          • 2012-03-13
          • 2017-06-08
          • 1970-01-01
          • 2016-04-12
          • 2017-06-01
          相关资源
          最近更新 更多