2013-07-21 5 views
15

Ho una situazione in cui il mio cliente sta cercando di scrivere una rappresentazione che comprende un elenco di di fkDjango serializzatori modello quadro riposo - leggi nidificato, scrivere piatta

{ 
languages: [1] 
last_name: "Beecher" 
settings: 1 
state: "NY" 
} 

Ma quando si legge in, mi piacerebbe avere una rappresentazione nidificato di ridurre il roundtrip

{ 
languages: [{id:1, created:2013-07-21T01:38:33.569Z, modified:2013-07-21T01:38:33.569Z, language:testing}] 
last_name: "Beecher" 
settings: { 
created: "2013-07-20T22:04:17.998Z" 
email_blog: false 
email_booking_accepted_denied: false 
email_booking_request: false 
email_friend_joined: false 
email_groups_added_network: false 
email_new_review: false 
email_news: false 
email_upcoming_booking_remind: false 
id: 1 
mobile_booking_accepted_denied: false 
mobile_booking_request: false 
mobile_friend_joined: false 
mobile_groups_added_network: false 
mobile_new_review: false 
mobile_upcoming_booking_remind: false 
modified: "2013-07-20T22:04:18.000Z" 
user: 1 
} 
state: "NY" 
} 

lettura non è un problema utilizzando un modello serializzatore e profondità = 1 -, ma il tentativo di scrivere dà un errore "ValueError ('istanza deve essere un set di query o altro iterabile con many = True ') " Durante il tentativo g per controllare molti campi correlati per iter

Al contrario, la disattivazione della profondità rende la scrittura come si desidera, ma la lettura non è buona.

C'è qualcosa che mi manca totalmente qui? Sembra che dovrebbe essere un semplice cambiamento, ma posso solo ottenere uno o l'altro lavoro

risposta

1

La cosa più semplice che mi viene in mente è di ignorare get_serializer_class() nella vista per POST/PUT per restituire un serializzatore modificato che non specifica il parametro di profondità e utilizzando PrimaryKeyRelatedField per il campo languages.

2

Ho avuto lo stesso problema e sembra che ce ne siano molti altri. La risposta Carlton Gibson mi porta effettivamente alla mia soluzione hacky. Ho finito per usare uno ModelSerializer con il set di profondità e ho creato il seguente mixin da usare nelle viste.

class ReadNestedWriteFlatMixin(object): 
    """ 
    Mixin that sets the depth of the serializer to 0 (flat) for writing operations. 
    For all other operations it keeps the depth specified in the serializer_class 
    """ 
    def get_serializer_class(self, *args, **kwargs): 
     serializer_class = super(ReadNestedWriteFlatMixin, self).get_serializer_class(*args, **kwargs) 
     if self.request.method in ['PATCH', 'POST', 'PUT']: 
      serializer_class.Meta.depth = 0 
     return serializer_class 
+0

È possibile eseguire a problemi mentre si scala con questo approccio. Meta è una variabile di livello di classe, condivisa da tutte le istanze. Mentre si attiva la profondità durante il tentativo di serializzare un oggetto, si pasticciano con TUTTE le istanze. – morgancodes

5

Grazie al post precedente, sono andato con una soluzione simile in base al largo get_serializer_class per questo.

Volevo anche essere in grado di modificare la classe serializzatore in base al metodo.

Innanzitutto, ho aggiunto un attributo alla classe di visualizzazione con un dizionario che associa i metodi di richiesta alle classi di serializzazione.

serializer_classes = { 
    'GET': NestedSerializer, 
    'POST': FlatSerializer 
} 

Quindi, ho definito un mixin da utilizzare dove voglio questo comportamento.

class SwappableSerializerMixin(object): 
    def get_serializer_class(self): 
     try: 
      return self.serializer_classes[self.request.method] 
     except AttributeError: 
      logger.debug('%(cls)s does not have the required serializer_classes' 
         'property' % {'cls': self.__class__.__name__}) 
      raise AttributeError 
     except KeyError: 
      logger.debug('request method %(method)s is not listed' 
         ' in %(cls)s serializer_classes' % 
         {'cls': self.__class__.__name__, 
          'method': self.request.method}) 
      # required if you don't include all the methods (option, etc) in your serializer_class 
      return super(SwappableSerializerMixin, self).get_serializer_class() es 
+0

Anche se ha funzionato bene, fallisce il primo tranne la funzionalità di documentazione su DRF 3.6.3 (http://www.django-rest-framework.org/topics/documenting-your-api/) – gabn88