2016-04-24 13 views
0

Gewöhnen Sie sich an Django Rest Framework von Tastypie kommen, aber es gibt ein Problem, wenn es um ManyToMany Felder geht.Django (DRF): Serialisieren und Deserialisieren eines ManyToMany-Felds anders?

Wenn das Feld serialisiert werden soll, ist es bevorzugt, seine vollständige Darstellung einzubeziehen, und dies ist leicht durch Hinzufügen eines ModelSerializers mit vielen = True und read_only = True möglich. Das Problem ist, dass ich das Kontofeld nicht speichern kann, da es jetzt leer erscheint.

Wenn ich versuche, zu entfernen read_only = True bekomme ich

TypeError: 'accounts' is an invalid keyword argument for this function 

Am besten ist es die vollständige Darstellung zu schicken, sondern erfordern nur die ID, wenn ein verwandtes POST (create) oder PUT (Update) empfangen.

POST:

{ 
    "profile" : "1", 
    "accounts" : ["1"], 
    "amount" : "101.00" 
} 

RESPONSE:

{ 
    "id": 92, 
    "accounts": [], 
    "date_by": null, 
    "amount": "101.00", 
    "shared": false, 
    "profile": 1 
} 

GET:

[ 
    { 
    "id": 45, 
    "accounts": [ 
     { 
     "account_local": { 
      "id": 3, 
      "last_balance": "100.00", 
     }, 
     "type": "LocalAccount" 
     } 
    ], 
    "date_by": null, 
    "amount": "100.00", 
    "shared": false, 
    "profile": 1 
    },] 

GoalSerializer

class GoalSerializer(serializers.ModelSerializer): 
    accounts = AccountSerializer(many=True, read_only=True) 

    class Meta: 
     model = Goal 

GoalViewSet

class GoalViewSet(GenericViewSet, mixins.RetrieveModelMixin, mixins.ListModelMixin, mixins.CreateModelMixin): 
    serializer_class = GoalSerializer 
    queryset = Goal.objects.none() 

    def get_queryset(self): 
     return Goal.objects.filter(profile=self.request.user) 

AccountSerializer

class AccountSerializer(serializers.ModelSerializer): 
    type = SerializerMethodField('get_account_class') 

    class Meta: 
     model = Account 
     fields = ('account_local','account_external', 'type') 
     depth = 1 

    def get_account_class(self, obj): 
     if isinstance(obj.get_actual(), LocalAccount): 
      return obj.get_actual().__class__.__name__ 
     elif isinstance(obj.get_actual(), ExternalAccount): 
      return obj.get_actual().get_actual().__class__.__name__ 
     else: 
      return "Error" 

    def to_representation(self, instance): 
     data = super(AccountSerializer, self).to_representation(instance) 

     if isinstance(instance.get_actual(), ExternalAccount): 
      serializer = ExternalAccountSerializerEMT(instance.account_external.get_actual()) 
      data['account_external'] = serializer.data 

     return data 
+0

Bitte werfen Sie einen Blick auf meine andere Antwort [hier] (http://stackoverflow.com/a/36299894/2549021). – AKS

Antwort

1

habe ich es geschafft, dies zu umgehen durch:

  • Ändern AccountSerializer mit einem
    def to_internal_value(self, data): return Account.objects.get(id=data)

  • das read_only Attribut auf dem Feld

    accounts = AccountSerializer(many=True)

Das Konto muss nur Entfernen einer ID sein, wenn POST'ing/PUT'ing und das gesamte Konto zurückgegeben wird, wenn GET'ing

+0

Erstellen von POSTed und PUT Viele-zu-viele Felder müssen immer mit benutzerdefiniertem Code behandelt werden und manchmal kann es etwas schmutzig werden. Ich musste oft meine eigenen 'create()' und 'update()' im Serializer schreiben. Ihre Lösung für diesen Fall scheint sehr minimal und in Ordnung zu sein. – pasztorpisti

+0

Ich musste einen Schutz hinzufügen, um sicherzustellen, dass die Konten tatsächlich dem Profil gehören, aber darüber hinaus ... –

Verwandte Themen