2009-10-23 5 views
18

sto serializzazione un gruppo di oggetti con:Rimuovere campo pk da Django oggetti serializzati

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

non ho incluso 'pk' nella mia lista campi, ma il prodotto JSON include una chiave primaria con ogni serializzato oggetto. Non voglio che la mia API esponga le chiavi primarie al pubblico in generale.

A corto di munging dell'output JSON, qual è il modo corretto per dire a serializers.serialze() di non includere la chiave primaria?

+0

@Josh Reich Che cosa si finisce per fare su questo? C'è un ticket che ne parla @ http://code.djopoproject.com/ticket/4656 – orokusaki

+0

Ho finito per chiamare manualmente simplejson –

risposta

16

ho finito per lavorare intorno a questo da 'manualmente' realizzare quello che volevo usare la sottostante simplejson serializzatore:

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

Un po 'più di battitura, ma funziona.

+0

è un'ottima soluzione se vuoi semplicemente scaricare alcuni dati su json e non preoccuparti di FK. –

+0

@Josh È molto più codificante se hai 28 metodi che usano 5 modelli in un'API. – orokusaki

+0

Ho usato questo. Ma è una seccatura quando la usi in più punti di vista. È meglio usare i serializzatori di Django. L'ultima risposta ha un collegamento a una domanda correlata, che spiega come rimuovere i campi pk e model dagli oggetti che genera. – Dmitry

0

Non perdiamo tempo a cercare di "disinfettare" i PK. Quando produciamo un record JSON, il PK è presente e l'utente può ignorarlo se lo desidera. Non possono fare nulla con le informazioni, quindi è solo confusione.

Nessuna delle nostre interfacce di servizi Web consente a chiunque di restituirci un PK. Effettuiamo ricerche POST, PUT e DELETE su altri campi, ma non sul PK.

L'HTML, tuttavia, mostra gli URL del PK tutto il tempo. Permette alle persone di aggiungere un segnalibro alle pagine.

+7

Molte aziende presumono che nessuna informazione sia contenuta all'interno di chiavi primarie sequenziali. Se hai i tuoi controlli di accesso bloccati, niente di cui preoccuparsi, giusto? sbagliato. Perlomeno, rivelando identificatori sequenziali fornisce un ottimo modo per i concorrenti di tenere traccia della vostra crescita. Esiste un settore considerevole basato semplicemente sulla ricerca di ID sequenziali e sulla vendita di stime di crescita. –

+0

È possibile avvicinarsi al problema utilizzando UUID anziché ID sequenziali, quindi esporli al pubblico non fornirà alcuna informazione per i concorrenti. –

+0

Considerare anche il testo aggiuntivo che viene inviato a ciascun utente quando viene incluso il pk e il modello. Questa è la larghezza di banda che potrebbe essere chiaramente salvata (specialmente quando si invia questo a un utente mobile). – shaond

3

Anche se questa è una vecchia domanda, qualcun altro lo troverà probabilmente su una ricerca Google.

Sfortunatamente il serializzatore django offre una personalizzazione piuttosto piccola come quella che hai definito. La mia soluzione, se sai che utilizzerai un sacco di serializzazione per il tuo progetto, è stato semplicemente copiare il materiale di serializzazione di django nel mio progetto e apportare alcune piccole modifiche. Questo non è l'ideale, ma fa il lavoro. In particolare, per rimuovere le PK, c'è una linea in start_object (auto, obj):

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

Rimozione della linea di "pk" dovrebbe risolvere il problema. È un trucco un po 'sporco, dal momento che se migliorano in seguito, potrebbe richiedere alcune modifiche alle tue visualizzazioni, ma per me questo era il modo più semplice per aggirare le limitazioni.

Spero che questo aiuti qualcuno.

7

Si può anche ignorare JSON serializzatore come spiegato qui: 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) 
+0

Grazie! La risposta di questa domanda ha aiutato molto! – Dmitry

0

Il modo più brutto (ma di lavoro):

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

Cosa Josh ha fatto, ma al contrario:

data = json.loads(json_string) 

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

data = json.dumps(data) 

in questo modo non devi preoccuparti di aggiornare il codice quando aggiungi altri campi nel futuro.

1

Ho avuto lo stesso problema, quindi ho creato il mio Serializer, ereditarietà da Serializer di Django. Vorrei solo i dati del campo, quindi sovrascrivo il metodo get_dump_object e aggiunto il campo 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 

E non chiamate:

output = JSONSerializer().serialize(queryset)