2014-04-10 18 views
39

Ich möchte einige Argumente DRF Serializer Klasse von Viewset passieren, also habe ich versucht, dieses:Pass zusätzliche Argumente Serializer Klasse in Django Rastrahmen

class OneZeroSerializer(rest_serializer.ModelSerializer): 

    def __init__(self, *args, **kwargs): 
     print args # show values that passed 

    location = rest_serializer.SerializerMethodField('get_alternate_name') 

    def get_alternate_name(self, obj): 
     return '' 


    class Meta: 
     model = OneZero 

     fields = ('id', 'location') 

Ansichten

class OneZeroViewSet(viewsets.ModelViewSet): 

    serializer_class = OneZeroSerializer(realpart=1) 
    #serializer_class = OneZeroSerializer 

    queryset = OneZero.objects.all() 

Grundsätzlich möchte ich einen Wert basierend auf Querystring von Ansichten zu Serializer-Klasse übergeben und dann werden diese Felder zugeordnet.

Diese Felder sind nicht in Model tatsächlich dynamisch erstellte Felder enthalten.

Gleicher Fall in dieser Frage stackoverflow, aber ich kann die Antwort nicht verstehen.

Kann mir jemand in diesem Fall helfen oder mir bessere Optionen vorschlagen.

+0

@PauloScardine können Sie mir einfaches Beispiel oder einen Link, wo ich Hilfe bekommen kann? Ich bin neu im Django, deshalb kann ich deine Worte nicht bekommen. –

+1

Die Antwort auf die Frage, auf die Sie verweisen, ist richtig. Lesen Sie die Dokumentation zur Methode "get_serializer" und überschreiben Sie sie, um eine benutzerdefinierte Instanz des Serializers zurückzugeben. –

+0

mögliches Duplikat von [Dynamisch modifizierende Serializerfelder in Django Rest Framework] (http: // stackoverflow.com/questions/18696403/dynamisch-modifizieren-serializer-felder-in-django-rest-framework) –

Antwort

5

Ein alter Code, den ich schrieb, dass verschachtelte Serializer hilfsbereit, filtern getan werden könnte:

class MySerializer(serializers.ModelSerializer): 

    field3 = serializers.SerializerMethodField('get_filtered_data') 

    def get_filtered_data(self, obj): 
     param_value = self.context['request'].QUERY_PARAMS.get('Param_name', None) 
     if param_value is not None: 
      try: 
       data = Other_model.objects.get(pk_field=obj, filter_field=param_value) 
      except: 
       return None 
      serializer = OtherSerializer(data) 
      return serializer.data 
     else: 
      print "Error stuff" 

    class Meta: 
     model = Model_name 
     fields = ('filed1', 'field2', 'field3') 

Wie get_serializer_class außer Kraft zu setzen:

class ViewName(generics.ListAPIView): 

    def get_serializer_class(self): 
     param_value = self.context['request'].QUERY_PARAMS.get('Param_name', None) 
     if param_value is not None: 
      return Serializer1 
     else: 
      return Serializer2 

    def get_queryset(self): 
     ..... 

Hope this dies für Menschen auf der Suche hilft.

+2

genau das, was ich brauchte, um Abfrageparameter zu erhalten, danke! Beachten Sie, dass der angezeigte Code veraltet ist. Um param-Werte zu erhalten, sieht es jetzt wie folgt aus: self.context ['request']. query_params.get() '. –

49

Es ist sehr einfach mit "Kontext" arg für "ModelSerializer" -Konstruktor.

Zum Beispiel:

im Blick:

my_objects = MyModelSerializer(
    input_collection, 
    many=True, 
    context={'user_id': request.user.id} 
).data 

in Serializer:

class MyModelSerializer(serializers.ModelSerializer): 
... 

    is_my_object = serializers.SerializerMethodField('_is_my_find') 
... 

    def _is_my_find(self, obj): 
     user_id = self.context.get("user_id") 
     if user_id: 
      return user_id in obj.my_objects.values_list("user_id", flat=True) 
     return False 
... 

so können Sie "self.context" für das Erhalten von Extra params verwenden.

Reference

+7

Dies funktioniert nicht..wenn ich den Kontext mit einem zusätzlichen Feld in meinem Serialisierer übergebe, fehlt dieses zusätzliche Feld und der Kontext sieht folgendermaßen aus: '{'Anfrage': , 'view': , 'format': None} ' – L3K0V

16

Um die Antwort von redcyb zu erfüllen - betrachten die get_serializer_context Methode von GenericAPIView Ihrer Ansicht verwenden, wie folgt aus:

def get_serializer_context(self): 
    return {'user': self.request.user.email} 
+3

Nur überschreiben' get_serializer_context' wird es nicht schneiden, weil die reale Stelle, an der 'valided_data' mit Kontext aktualisiert wird,' serializer.save() 'Methode ist , die von 'ViewSet.update() -> ViewSet.perform_update()' und 'ViewSet.create() -> ViewSet.perform_create()' aufgerufen wird. Aber der Haken ist, dass sie '** kwargs' mit Kontext nicht an' save() 'übergeben. Um also den Kontext zu mischen, müssen wir 'perform_create' und' perform_update' überschreiben, damit sie den Kontext an 'save()' weitergeben. –

7

Sie im Ansicht Überschreibung get_serializer_context Methode wie folgt benötigen:

def get_serializer_context(self): 
    return {"customer_id": self.kwargs['customer_id']} 

und überall in der serializer Sie können es erhalten:

customer_id = self.context["customer_id"] 
Verwandte Themen