2013-02-17 15 views
8

Ho il seguente serializzatore che utilizza Django REST Framework.Rest Framework Serializer Method

Questo è ciò che ho finora ...

serializer.py

class ProductSerializer(serializers.ModelSerializer): 

    score = serializers.SerializerMethodField('get_this_score') 

    class Meta: 
     model = Product 
     fields = ('id', 'title', 'active', 'score') 

    def get_this_score(self, obj): 

     profile = Profile.objects.get(pk=19) 
     score = [val for val in obj.attribute_answers.all() if val in profile.attribute_answers.all()] 
     return (len(score)) 

urls.py

url(r'^products/(?P<profile_id>.+)/$', ProductListScore.as_view(), name='product-list-score'), 

Ci sono alcuni problemi con questo frammento di codice.

1) La carrozzina pk = 19 è hardcoded dovrebbe essere self.kwargs['profile_id']. Ho provato e provato, ma non so come passare kwarg nel metodo e non può ottenere profile_id per funzionare. Ad esempio, non riesco a ottenerlo dall'URL.

2) Qualcuno di questo codice dovrebbe essere nei modelli? Ho provato ad aggiungere ai modelli, ma ancora una volta posso passare gli arg.

models.py cioè metodo di classe

 def get_score(self, profile): 

     score = [val for val in self.attribute_answers.all() if val in 
profile.attribute_answers.all()] 
      return len(score) 

risposta

21

Serializzatori sono passati un dizionario contesto, che contiene l'istanza di vista, così si potrebbe ottenere il profile_id facendo qualcosa di simile a questo:

view = self.context['view'] 
profile_id = int(view.kwargs['profile_id']) 

Tuttavia in questo caso non penso che sia necessario farlo poiché 'obj' sarà in ogni caso impostato sull'istanza del profilo.

E sì, è possibile inserire il metodo 'get_this_score' nella classe del modello. Avresti ancora bisogno del "SerializerMethodField", ma chiamerebbe semplicemente "return obj.get_this_score (...)", impostando qualsiasi argomento dal contesto serializzatore.

Si noti che il contesto serializzatore includerà anche "richiesta", quindi è possibile accedere anche a "request.user", se necessario.

+1

Mi piace l'idea di avere questo nei modelli. ma SerializerMethodField usando source = non mi permette di passare i parms. potresti darmi un esempio dell'uso di SerializerMethodField e del passaggio degli argomenti di richiesta più l'oggetto a un metodo di modello? questo mi aiuterebbe davvero a capire. Grazie. – jason

+0

Mi unisco alla domanda di @jason –

+0

in 'Tuttavia in questo caso non penso che sia necessario farlo poiché 'obj' sarà in ogni caso impostato sull'istanza del profilo 'vuoi dire istanza' Product' forse? – Pynchia

7

Per rispondere alla domanda risposta di Jason alla risposta di Tom è possibile accedere all'oggetto richiesta tramite lo stesso meccanismo di contesto in questo modo. Si fa riferimento agli oggetti richiesta dalla definizione ModelMethod, non li si passa. Sono stato in grado di utilizzare questo per accedere all'attuale oggetto request.user come di seguito:

class ProductSerializer(serializers.ModelSerializer): 
    score = serializers.SerializerMethodField('get_this_score') 

    class Meta: 
     model = Product 
     fields = ('id', 'title', 'active', 'score') 

    def get_this_score(self, obj): 

     profile = self.context['request'].user 
     score = [val for val in obj.attribute_answers.all() if val in profile.attribute_answers.all()] 
     return (len(score)) 
+0

Grazie amico, le tue soluzioni funzionano per me! –

+0

Quando uso questo serializzatore con CBV funziona bene, ma quando ho usato questo serializzatore con FBV 'return Response ({'data': ProductSerializer (user_profiles, many = True) .data})' Sto ottenendo richiesta di keyerror –

+0

risolto da [incluso il contesto extra] (http://www.django-rest-framework.org/api-guide/serializers/#including-extra-context) –

Problemi correlati