2016-07-19 141 views
7

Ho modello con molti collegamenti in esso:Come posso creare un'istanza del modello tramite Serializer senza creare modelli da serialziers nidificati?

class Travel(BaseAbstractModel): 

    tags = models.ManyToManyField(
     Tag, 
     related_name='travels', 
     ) 
    owner = models.ForeignKey(
     'users.TravelUser', 
     related_name='travel_owner' 
     ) 
    payment = models.ForeignKey(
     Payment, 
     related_name='travels', 
     ) 
    country = models.ForeignKey(
     Country, 
     related_name='travels, 
     ) 
    ........ 

Molti di questi modelli hanno solo due campi con nome e immagine unica. creo serializzatore per ciascuno di questi modelli e metterli in TravelSerializer

class TravelBaseSerializer(DynamicFieldsModelSerializer): 

    owner = UserSerializer(required=False) 
    tags = TagSerializer(many=True) 
    payment = PaymentSerializer() 
    country = CountrySerializer() 

Sulla base di documenti sovrascrivo create() e update.
Il problema è che quando ho inviato i dati JSON, Django crea ciascun modello da serializzatori nidificati. Ma voglio creare solo l'istanza Travel. Inoltre desidero ricevere e rispondere agli oggetti serializzati non solo nel campo pk.

UPDATE
Ho risolto questo problema, inserire il codice nella risposta. Ora posso ricevere e rispondere con dati Serializer senza creare oggetti. Ma penso che il DRF offra un approccio più elegante di quello che faccio io. È il mio primo progetto con DRF, forse mi manca qualcosa e c'è una soluzione più semplice.

risposta

2

decido di override to_internal_value() metterlo in serailizer costume e ereditano tutte serializzatori annidati da esso:

class NestedRelatedSerializer(serializers.ModelSerializer): 

    def to_internal_value(self, data): 
     try: 
      pk = data['pk'] 
     except (TypeError, KeyError): 
     # parse pk from request JSON 
      raise serializers.ValidationError({'_error': 'object must provide pk!'}) 
     return pk 

Ricevi tutte pk da esso e salvare in create e updated metodi:

def update(self, instance, validated_data): 
     # If don't get instance from db, m2m field won't update immediately 
     # I don't understand why 
     instance = Travel.objects.get(pk=instance.pk) 
     instance.payment_id = validated_data.get('payment', instance.payment_id) 
     instance.country_id = validated_data.get('country', instance.country_id) 
     # update m2m links 
     instance.tags.clear() 
     instance.tags.add(*validated_data.get('tags')) 
     instance.save() 
     return instance 
1

I' Non sono proprio sicuro di aver capito cosa vuoi fare, ma potresti impostare read_only_fields la classe Meta essere ciò di cui hai bisogno?

class TravelBaseSerializer(DynamicFieldsModelSerializer): 

    owner = UserSerializer(required=False) 
    tags = TagSerializer(many=True) 
    payment = PaymentSerializer() 
    country = CountrySerializer() 

    class Meta: 
     read_only_fields = ('tags',) 

Vedere this section nei documenti.

+0

Grazie, ma l'ho provato nella prima cosa. Problema con 'read_only_fields', questi campi non passano a' validated_data' –

+0

OK, quindi quello che penso che tu voglia è questo: lo vuoi quando il serializzatore viene usato per leggere le puprose, serializza tutti i campi relativi e quando viene usato per scrivere puprose prova a convalidare i campi correlati ma non li salva. Per favore correggimi se sbaglio. – AntoineWDG

+0

sì, ma ho bisogno di questi dati in 'validated_data', perché ho bisogno di riempire tutti i campi link nel modello creato 'Travel'. Lo risolvo, come puoi vedere nella mia risposta. Ma inizio questa taglia, perché, voglio trovare delle buone pratiche, per scopi come questo. Ora penso che DRF non permetta l'uso di serializzatori nidificati per scopi del genere, per impostazione predefinita –