2015-10-20 22 views
7

Podczas korzystania z Django-REST-Framework, nie jestem w stanie wyświetlić wybranych pól w zagnieżdżonym serializowanym obiekcie.Django Rest Framework - Serializacja zagnieżdżona nie działa zgodnie z oczekiwaniami

Mam poprawną możliwość serializowania całego modelu Address, ale chcę tylko kilka pól z Address, zagnieżdżonych w moim serializowanym Outlet. Jest

Got AttributeError gdy próbuje uzyskać wartość pola outlet_address na serializatora OutletSerializer. Pole serializera może mieć niepoprawną nazwę i nie pasuje do żadnego atrybutu ani klucza w instancji Outlet. Oryginalny tekst wyjątku: Obiekt "Outlet" nie ma atrybutu "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 

W tym momencie, nie jest w stanie znaleźć outlet_address atrybut w modelu Outlet podczas gdy spodziewam się, że powinno być możliwe w serializatorze.

Got AttributeError gdy próbuje uzyskać wartość dla pola outlet_address na serializatora OutletSerializer. Pole serializatora może być nazwane niepoprawnie i nie pasuje do żadnego atrybutu ani klucza w instancji instancji Outlet. Oryginalny tekst wyjątku: obiekt "Outlet" nie ma atrybutu "outlet_address".

Jak opisano w innych odpowiedzi, próbowałem:

  1. dodanie many= do ModelSerializer
  2. dodając related_name= do wszystkich modeli

Odpowiedz

9

Spróbuj tego:

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 

powodem chciałbym dokonać zmian powyżej, ponieważ model Outlet nie posiada atrybut o nazwie „outlet_address” ma atrybut o nazwie "adres".

Zobacz tutaj podobnego problemu: Django Rest framework keeps returning error on nested relationship

+0

widziałem połączony artykuł wcześniej, ale to było dla zacofanych relacji. Swoje prace odpowiedź doskonale, a teraz rozumiem nieco lepiej magię DRF. – Pranab

3

model Outlet posiada polu "Adres", nie jest adresem wyjściowym. Radziłbym, aby ustawić serializatora tak:

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

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

Dodatkowo do innych odpowiedzi, chciałbym dodać co następuje w przypadku kogoś ląduje tu.

Zagnieżdżona serializacja wymaga, aby nazwa pola znajdowała się w polach modelu, aby mogła działać.

W przypadku, gdy potrzebujemy reverse relation, oczywiście nie będzie takiego pola w polach modelu.

Na przykład, w przypadku poszczególnych modeli w pytaniu, stanie się tak, jeśli będziemy potrzebować odniesienia do wszystkich rynków zbytu w serializatorze adresów.

Dlatego musimy: (a) określić related_name na klucz obcy w innym modelu. Tutaj będziemy używać outlet_address, ponieważ jest to powiązana nazwa pola adresu w modelu gniazdka.

lub (b) jeżeli nie związane nazwa następnie użyj domyślnej nazwy Django, dołączając _set do nazwy modelu (np outlet_set.