2016-04-07 24 views
12

mam usign Django Framework Rest gdzie mam następujące dwa serializers:modelu Django Framework Reszta Id pola zagnieżdżone w związku serializatora

class ServiceSerializer(serializers.ModelSerializer): 
    id = serializers.ReadOnlyField() 

    class Meta: 
     model = ServiceType 
     fields = ('id', 'serviceName', 'servicePrice') 


class CompanyShortListSerializer(serializers.ModelSerializer): 

    services = ServiceSerializer(many=True) 

    class Meta: 
     model = Company 
     fields = ('id','name','address','cost_per_patient','cost_per_month','renting_fee','services') 

Model ServiceType wygląda następująco:

class ServiceType(models.Model): 
    serviceName = EncryptedCharField(max_length=100, blank=True, verbose_name = "Typ usługi") 
    servicePrice = EncryptedFloatField(null=True, blank=True, verbose_name = "Cena usługi", validators = [MinValueValidator(0.1), MaxValueValidator(999)]) 
    company = models.ForeignKey(Company, related_name = 'services') 

I chciałby zaktualizować istniejące instancje, zmieniając powiązane usługi (np. usuwając niektóre z nich). Aby to osiągnąć, że to robię:

def update(self, instance, validated_data): 
    # Updates an exisitng Company with several services 
    instance.name = validated_data['name'] 
    instance.address = validated_data['address'] 
    instance.cost_per_patient = validated_data['cost_per_patient'] 
    instance.renting_fee = validated_data['renting_fee'] 
    services_data = validated_data['services'] 

    for item in services_data: 
     updatedService = ServiceType(
      serviceName = item['serviceName'], 
      servicePrice = item['servicePrice'], 
      id=item['id'], 
      company=instance) 
     updatedService.save() 

    return instance 

problem, że jestem stoi to, że pole service['id'] nie jest - co oznacza, że ​​mogę dostać KeyError 'id' - chociaż dodałem go wyraźnie w dziedzinie ServiceSerializerid.

EDIT

Oto przykładowy wniosek (wzięte z Chrome), że jestem delegowania:

{ "id":49,"name":"Test 1", 
    "address":"Testowa 1", 
    "renting_fee":200, 
    "cost_per_month":300, 
    "cost_per_patient":null, 
    "services":[ 
    {"id":67,"serviceName":"Terapia","servicePrice":100}, 
    {"id":68,"serviceName":"Terapia par","servicePrice":150}, 
    {"id":69,"serviceName":"Terapia po angielsku","servicePrice":120} 
    ] 
} 

Co robię źle i jak uzyskać identyfikator w obiekcie (w zasadzie ServiceSerializer) za pomocą zagnieżdżonych serializerów?

EDIT no.2

Podczas drukowania z funkcji aktualizacji serializer otrzymuję następujący:

print(self.data['services']) daje mi:

[ 
OrderedDict([('id', 67), ('serviceName', u'Terapia'), ('servicePrice', 100.0)]), 
OrderedDict([('id', 68), ('serviceName', u'Terapia par'), ('servicePrice', 150.0)]), 
OrderedDict([('id', 69), ('serviceName', u'Terapia po angielsku'), ('servicePrice', 120.0)]), 
OrderedDict([('id', 70), ('serviceName', u'Terapia grupowa'), ('servicePrice', 140.0)]) 
] 

Jednak print(services_data) daje następujące (w zasadzie to samo, ale bez identyfikatora):

[ 
OrderedDict([(u'serviceName', u'Terapia'), (u'servicePrice', 100.0)]), 
OrderedDict([(u'serviceName', u'Terapia par'), (u'servicePrice', 150.0)]), 
OrderedDict([(u'serviceName', u'Terapia po angielsku'), (u'servicePrice', 120.0)]) 
] 

A ids zgubić ...

EDIT No.3

Według Django Rest Framework docs Jeśli jakieś pole to będzie będzie w reprezentacji serializer wyjściowym powinno być HiddenField. To jednak wymaga wartości default ... Sprawdziłem to i rzeczywiście używając tej HiddenField z domyślną wartością "rozwiązuje" problem - identyfikator jest tam w validated_data. Problem polega na tym, że id nie jest poprawny. Czy istnieje możliwość ustawienia wartości id na wartość obiektu wysłanego do serializera?

Odpowiedz

15

Ok - Myślę, że znalazłem odpowiedź po ...uważnie czyta the docs :)

Więc według the docs pole id może być ustawiony na ModelField tak:

id = serializers.ModelField(model_field=ServiceType()._meta.get_field('id')) 

Rzeczywiście, po dodaniu tej linii boiska id jest obecny w validated_data :)

+4

Dzięki, uratowałeś mi dzień :-) – bre

+0

Właśnie uratowałeś inne życie !. Dokumenty DRF to labirynt. Ważne informacje są ukryte w dokumentach. Dzięki – danidee

2

Ustawiono id jako ReadOnlyField. Dlatego id nie pojawia się w sprawdzonych danych. Po prostu usuń tę linię:

id = serializers.ReadOnlyField() 
+0

Niestety, po usunięciu tego ja wciąż 'KeyError„id” 'z serializatora ... :( – user1544500

+0

jaki sposób JSON wyglądać, że pisać można dodać to do listy pytanie? – ilse2005

+0

Dodałem przykładową prośbę z Chrome. Mam nadzieję, że to wystarczy? – user1544500

4

Przyjęta odpowiedź działa, ale jest niepotrzebnie skomplikowana. Możesz po prostu zmienić pole ID, aby nie było tylko do odczytu. Na przykład. coś takiego zrobi?

id = serializers.IntegerField(required=False) 
+0

Rzeczywiście, działa również. –

Powiązane problemy