2014-04-10 2 views
39

Chcę przekazać niektóre argumenty do klasy DRF Serializatora od Viewset, więc dla Próbowałem to:przekazać dodatkowe argumenty do Serializatora klasy w Django Rest ram

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') 

Wyświetleń

class OneZeroViewSet(viewsets.ModelViewSet): 

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

    queryset = OneZero.objects.all() 

Zasadniczo chcę przekazać pewne wartości na podstawie querystring z widoków do klasy Serializer, a następnie będą one alokować do pól.

Te pola nie są uwzględniane w modelu w rzeczywistości w dynamicznie utworzonych polach.

Ten sam przypadek w tym pytaniu stackoverflow, ale nie mogę zrozumieć odpowiedzi.

Czy ktoś może mi pomóc w tej sprawie lub zaproponować mi lepsze opcje.

+0

@PauloScardine możesz podać mi prosty przykład lub dowolny link, w którym mogę uzyskać pomoc? Jestem nowy w django, dlatego nie mogę uzyskać twoich słów. –

+1

Odpowiedź na pytanie, które odsyłasz jest właściwa, przejdź do dokumentacji metody 'get_serializer' i zastąp ją, aby zwrócić niestandardową instancję serializera. –

+0

możliwy duplikat [Dynamicznie modyfikujący serializer pól w Django Rest Framework] (http: // stackoverflow.com/questions/18696403/dynamic-modifying-serializer-fields-in-django-rest-framework) –

Odpowiedz

5

Stare kod pisałem, że może być pomocny-zrobić filtrowanie zagnieżdżonych serializatora:

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') 

Jak przesłonić get_serializer_class:

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

Nadzieja pomaga to ludzie patrząc na to.

+2

dokładnie to, czego potrzebowałem przy uzyskiwaniu parametrów zapytań, dzięki! Zauważ, że wyświetlany kod jest przestarzały. aby uzyskać wartości param, wygląda teraz jak 'self.context ['request']. query_params.get()'. –

49

To bardzo proste z argonem "context" dla konstruktora "ModelSerializer".

Na przykład:

w widoku:

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

w serializers:

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

więc można użyć "self.context" dla uzyskania dodatkowych params.

Reference

+7

To nie działa. Kiedy przekazuję kontekst z dodatkowym polem w moim serializatorze, to dodatkowe pole jest niedostępne, a kontekst wygląda następująco: '{'request': , 'view': , 'format': Brak} ' – L3K0V

16

Aby spełnić odpowiedź redcyb - rozważyć użycie w widoku metodę get_serializer_context z GenericAPIView, tak:

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

Po prostu przesłonięcie' get_serializer_context' nie spowoduje jego przecięcia, ponieważ prawdziwym miejscem, gdzie 'validated_data' jest aktualizowana kontekstem jest' serializer.save() 'method , który jest wywoływany przez 'ViewSet.update() -> ViewSet.perform_update()' i 'ViewSet.create() -> ViewSet.perform_create()'. Ale haczyk polega na tym, że nie przekazują one '** kwargs' z kontekstem do' save() '. Tak więc, aby połączyć kontekst, będziemy musieli przesłonić 'perform_create' oraz' perform_update', aby przekazać kontekst do 'save()'. –

7

Musisz w View override get_serializer_context metoda tak:

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

i dowolnym miejscu w serializer możesz go otrzymać:

customer_id = self.context["customer_id"]