2016-04-07 18 views
12

sto usign Django Resto quadro dove Ho le seguenti due serializzatori:modello di Django Resto quadro campo Id in relazione annidata serializzatore

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') 

Il modello ServiceType assomiglia a questo:

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 desidera aggiornare le istanze esistenti modificando i relativi servizi (ad esempio eliminandone alcuni). Per raggiungere questo obiettivo che sto facendo questo:

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 

Il problema che sto affrontando è che il campo service['id'] non è previsto - il che significa che ottengo un KeyError 'id' - anche se ho aggiunto esplicitamente nel campo ServiceSerializerid.

EDIT

Ecco una richiesta di esemplari (tratto da Chrome) che sto postando:

{ "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} 
    ] 
} 

Che cosa sto facendo di sbagliato e come ottenere l'ID di un oggetto (in pratica ServiceSerializer) utilizzando serializzatori nidificati?

EDIT no.2

Quando stampo dalla funzione di aggiornamento serializzatore ottengo il seguente:

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

[ 
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)]) 
] 

Tuttavia, print(services_data) ha pronunciato la seguente (in pratica lo stesso, ma senza l'id):

[ 
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)]) 
] 

E il ids perdersi ...

EDIT no.3

Secondo il Django Rest Framework docs Se certo campo sarà deve essere nella rappresentazione uscita serializzatore dovrebbe essere un HiddenField. Ciò tuttavia richiede un valore default ... L'ho verificato e, in effetti, l'utilizzo di questo HiddenField con un valore predefinito "risolve" il problema: l'ID è presente in data validated. Il problema è che id non è corretto. C'è la possibilità di impostare questo id sul valore dell'oggetto inviato al serializzatore?

risposta

15

Ok - Penso di aver trovato la risposta dopo ...leggere attentamente the docs :)

Quindi, secondo the docs campo id potrebbe essere impostata su un ModelField come questo:

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

In effetti, dopo l'aggiunta di questa riga il campo id è presente in validated_data :)

+4

Grazie, hai salvato la mia giornata :-) – bre

+0

Hai appena salvato un'altra vita !. I documenti DRF sono un labirinto. Informazioni importanti sono nascoste in profondità nei documenti. Grazie – danidee

2

Hai impostato id come ReadOnlyField. Ecco perché id non appare nei dati convalidati. Basta rimuovere questa riga:

id = serializers.ReadOnlyField() 
+0

Purtroppo, dopo la rimozione di questo ho ancora 'KeyError 'id' 'dal serializzatore ... :( – user1544500

+0

modo la JSON sguardo che si posta Puoi aggiungere questo alla tua domanda? – ilse2005

+0

Ho aggiunto una richiesta esemplare da Chrome. Spero che sia abbastanza? – user1544500

4

La risposta accettata funziona ma è inutilmente complicata. Puoi semplicemente cambiare il campo ID per non essere di sola lettura. Per esempio. qualcosa di simile a questo farà:?

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

Effettivamente, funziona anche. –

Problemi correlati