Josh Reich
Josh Reich

Reputation: 6607

Remove pk field from django serialized objects

I'm serializing a bunch of objects with:

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

I have not included 'pk' in my fields list, but the produced JSON includes a primary key with each serialized object. I do not want my API to expose primary keys to the general public.

Short of munging the output JSON, what is the correct way to tell serializers.serialze() to not include the primary key?

Upvotes: 21

Views: 15591

Answers (7)

dev.gabriel.lima
dev.gabriel.lima

Reputation: 31

I had the same problem, so I created my own Serializer, inheritance from Serializer from Django. I'd like only field's data, so I overwrite the method get_dump_object, and added the PK field.

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

And call:

output = JSONSerializer().serialize(queryset)

Upvotes: 3

nonameentername
nonameentername

Reputation: 434

What Josh did but backwards:

data = json.loads(json_string)

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

data = json.dumps(data)

this way you don't have to worry about updating the code when adding more fields in the future.

Upvotes: 13

Bruno Barbieri
Bruno Barbieri

Reputation: 7

The ugly (but working) way :

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

Upvotes: -1

Pedro Andrade
Pedro Andrade

Reputation: 4634

You may also override JSON serializer as explained here: 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)

Upvotes: 9

philipk
philipk

Reputation: 1483

Although this is an old question, someone else will probably come up with it on a Google search.

Unfortunately the django serializer offers fairly little customization like what you defined. My solution, if you know you will be using a lot of serialization for your project, was simply to copy django's serialization stuff over to my own project and make some small changes. This isn't ideal, but it does the job. Specifically, to remove the pk's, there is a line in start_object(self, obj):

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

Removing the "pk" line should fix it. It's a somewhat dirty hack, since if they improve this later on it may require some changes to your views, but for me this was the easiest way around the limitations.

Hope this helps someone.

Upvotes: 3

Josh Reich
Josh Reich

Reputation: 6607

I ended up working around this by 'manually' achieving what I wanted using the underlying simplejson serializer:

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

A little more typing, but works.

Upvotes: 18

S.Lott
S.Lott

Reputation: 391872

We don't waste our time trying to "sanitize" the PK's. When we produce a JSON record, the PK is there, and the user can ignore it if they want. They can't do anything with the information, so it's just clutter.

None of our web services interfaces allow anyone to provide a PK back to us. We do POST, PUT and DELETE searches on other fields, but not the PK.

The HTML, however, shows the PK's the URL's all the time. It lets people bookmark the pages.

Upvotes: -3

Related Questions