2015-10-20 12 views
7

Durante l'utilizzo di Django-REST-Framework, non sono in grado di visualizzare i campi selezionati in un oggetto serializzato nidificato.Django Rest Framework - La serializzazione nidificata non funziona come previsto

Sono correttamente in grado di serializzare la totalità del modello Address, ma desidero solo alcuni campi da Address, nidificati nel mio serializzato Outlet. C'è un

Got AttributeError quando si cerca di ottenere un valore per il campo outlet_address su serializer OutletSerializer. Il campo serializzatore potrebbe essere denominato in modo errato e non corrispondere a nessun attributo o chiave nell'istanza Outlet. Il testo di eccezione originale era: l'oggetto 'Outlet' non ha attributo 'outlet_address'.

api_v1/models.py

class Address(models.Model): 
    building = models.CharField(_("shop number, floor & building"), max_length=128) 
    street = models.CharField(_("street"), max_length=128, blank=True) 
    area = models.ManyToManyField(Area, related_name='address') 
    city = models.ForeignKey(City, related_name='address') 
    pin_code = models.CharField(_("PIN code"), max_length=6, default="") 

    def __unicode__(self): 
     return self.building + " " + self.street + " ..." 


class Outlet(models.Model): 
    name = models.CharField(max_length=100, blank=True) 
    chain = models.ForeignKey(Chain, related_name='outlet', blank=True, null=True) 
    organization = models.ForeignKey(Organization, blank=True, null=True) 
    address = models.OneToOneField(Address, related_name='outlet_address') 
    thumbnail = AjaxImageField(upload_to='thumbnails', 
           max_height=200, #optional 
           max_width=200, # optional 
           crop=True) # optional 
    date_created = models.DateTimeField(_('date created'), default=timezone.now) 

    def __unicode__(self): 
     return self.name 

api_v1/serializers.py

from rest_framework import serializers 
from api_v1.models import Outlet, Address 

class AddressSerializer(serializers.ModelSerializer): 
    #address_area = AreaSerializer(many=False) 

    class Meta: 
     model = Address 
     fields = ('building', 'street',) 
     depth = 3 


class OutletSerializer(serializers.ModelSerializer): 
    outlet_address = AddressSerializer(many=False) 
    #area = serializers.CharField(source='address.area') #multiple levels of nesting? 

    class Meta: 
     model = Outlet 
     fields = ('id', 'name', 'thumbnail', 'outlet_address') 
     # fields = ('id', 'name', 'thumbnail', 'address') # this works 
     depth = 3 

A questo punto, non è in grado di trovare l'attributo outlet_address nel modello outlet mentre mi aspetto che dovrebbe essere in grado nel serializzatore.

Got AttributeError quando si cerca di ottenere un valore per il campo outlet_address sul serializzatore OutletSerializer. Il campo serializzatore potrebbe essere denominato in modo errato e non corrispondere a nessun attributo o chiave su l'istanza Outlet. Il testo originale dell'eccezione era: L'oggetto 'Outlet' non ha attributo 'outlet_address'.

Come descritto in altre risposte, ho provato:

  1. aggiungendo many= al ModelSerializer
  2. aggiungendo related_name= a tutti i modelli

risposta

9

Prova questa:

from rest_framework import serializers 
from api_v1.models import Outlet, Address 

class AddressSerializer(serializers.ModelSerializer): 

    class Meta: 
     model = Address 
     fields = ('building', 'street',) 
     depth = 3 


class OutletSerializer(serializers.ModelSerializer): 
    address = AddressSerializer(many=False) # make it address, not outlet_address 

    class Meta: 
     model = Outlet 
     fields = ('id', 'name', 'thumbnail', 'address') # make this address as well, not outlet_address 
     depth = 3 

La ragione per cui vorrei fare i cambiamenti di cui sopra è perché il modello outlet non ha un attributo chiamato "outlet_address", ha un attributo chiamato "indirizzo".

vedi qui per un problema analogo: Django Rest framework keeps returning error on nested relationship

+0

ho visto l'articolo collegato in precedenza, ma era per i rapporti arretrati. I suoi lavori risposta perfettamente e anche ora capisco la magia del DRF un po 'meglio. Grazie! – Pranab

3

Modello uscita ha un campo "indirizzo", non un outlet_address. Vorrei consigliare di impostare il serializzatore in questo modo:

class OutletSerializer(serializers.ModelSerializer): 
    address = AddressSerializer(many=False) 

    class Meta: 
     model = Outlet 
     fields = ('id', 'name', 'thumbnail', 'address') 
     depth = 2 
7

In aggiunta alle altre risposte, vorrei aggiungere quanto segue nel caso qualcuno atterra anche qui.

La serializzazione nidificata richiede che il nome del campo sia nei campi del modello per funzionare.

Nel caso in cui abbiamo bisogno di un reverse relation, ovviamente non ci sarà tale campo nei campi del modello.

Ad esempio, con i particolari modelli nella domanda, ciò accadrebbe se avessimo bisogno di fare riferimento a tutte le prese nel serializzatore di indirizzo.

Pertanto, è necessario: (a) specificare uno related_name nella chiave esterna dell'altro modello. Questo è dove useremmo outlet_address, poiché questo è il nome del campo indirizzo relativo nel modello di presa.

Or (b) se nessun nome relativo quindi utilizzare il nome predefinito Django, aggiungendo _set al nome del modello (ad esempio outlet_set.