2016-07-19 17 views
7

mam model z wielu linków do niego:Jak utworzyć instancję modelu przez Serializer bez tworzenia modeli z zagnieżdżonych szeregowych?

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, 
     ) 
    ........ 

Wiele z tych modeli ma tylko dwa pola z unikalnej nazwy i wizerunku. tworzę serializatora dla każdego z tych modeli i umieścić je w TravelSerializer

class TravelBaseSerializer(DynamicFieldsModelSerializer): 

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

podstawie Dokumentów zastąpić create() i update.
Problem polega na tym, że podczas wysyłania danych JSON, Django należy utworzyć każdy model z zagnieżdżonych serializerów. Ale chcę utworzyć tylko instancję Travel. Również chcę otrzymywać i odpowiadać na serializowane obiekty nie tylko w polu pk.

UPDATE
Rozwiązałem ten problem, umieściłem kod w odpowiedzi. Teraz mogę odbierać dane Serializera i odpowiadać na nie bez tworzenia obiektu. Ale myślę, że DRF zapewnia bardziej eleganckie podejście niż ja. To mój pierwszy projekt z DRF, może coś mi umknęło i jest łatwiejsze rozwiązanie.

Odpowiedz

2

zdecyduję przesłanianie to_internal_value() umieścić go w niestandardowym serailizer i dziedziczą wszystkie zagnieżdżone serializers od niego:

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 

Pobierz wszystkie pk z niego i zapisywać w create i updated metod:

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 nie jestem do końca pewny, że rozumiem, co chcesz zrobić, ale czy ustawienie read_only_fields jest klasą Meta, której potrzebujesz?

class TravelBaseSerializer(DynamicFieldsModelSerializer): 

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

    class Meta: 
     read_only_fields = ('tags',) 

Zobacz w dokumentach this section.

+0

Dziękuję, ale spróbowałem w pierwszej kolejności. Problem z 'read_only_fields', te pola nie przechodzą do' validated_data' –

+0

OK, więc myślę, że chcesz to: chcesz, gdy twój serializer jest używany do czytania puproses, serializuje on wszystkie powiązane pola i kiedy jest używany do pisania puproses próbuje zweryfikować powiązane pola, ale ich nie zapisuje. Proszę popraw mnie jeżeli się mylę. – AntoineWDG

+0

tak, ale potrzebuję tych danych w 'validated_data', ponieważ muszę wypełnić wszystkie pola odnośników w stworzonym modelu' Travel'. Rozwiązuję to, jak widać w mojej odpowiedzi. Ale ja zaczynam tę nagrodę, ponieważ chcę znaleźć najlepszą praktykę do takich celów. Teraz myślę, że DRF po prostu nie zezwala na używanie zagnieżdżonych serializerów do takich celów, domyślnie –