web-dev-qa-db-fra.com

Transmettez le contexte de requête au sérialiseur à partir du Viewset dans Django Rest Framework

J'ai un cas où les valeurs d'un champ de sérialiseur dépendent de l'identité de l'utilisateur actuellement connecté. J'ai vu comment ajouter l'utilisateur au contexte lors de l'initialisation d'un sérialiseur, mais je ne suis pas sûr de savoir comment procéder lors de l'utilisation d'un ViewSet, car vous ne fournissez que la classe de sérialiseur et non l'instance de sérialiseur.

En gros, j'aimerais savoir comment aller de:

class myModelViewSet(ModelViewSet):
   queryset = myModel.objects.all()
   permission_classes = [DjangoModelPermissions]
   serializer_class = myModelSerializer

à:

class myModelSerializer(serializers.ModelSerializer):
    uploaded_by = serializers.SerializerMethodField()
    special_field = serializers.SerializerMethodField()

    class Meta:
        model = myModel

    def get_special_field(self, obj):
        if self.context['request'].user.has_perm('something.add_something'):
           return something

Désolé si ce n'était pas clair, d'après les DOC: Ajout d'un contexte supplémentaire Ce qui dit de faire 

serializer = AccountSerializer(account, context={'request': request})
serializer.data

Mais je ne suis pas sûr de savoir comment le faire automatiquement à partir de la vue, car je ne peux que changer de classe de sérialiseur, et pas l'instance de sérialiseur elle-même.

42
oowowaee

GenericViewSet a la méthode get_serializer_context que vous pouvez remplacer:

class myModelViewSet(ModelViewSet):
    queryset = myModel.objects.all()
    permission_classes = [DjangoModelPermissions]
    serializer_class = myModelSerializer

    def get_serializer_context(self):
        return {'request': self.request}
60
Syslo

Renvoyer le contexte parent dans la fonction remplacée get_serializer_context facilitera l'accès à la demande et à ses données. 

 class myModelViewSet(ModelViewSet):
       queryset = myModel.objects.all()
       permission_classes = [DjangoModelPermissions]
       serializer_class = myModelSerializer

       def get_serializer_context(self):
       """
       pass request attribute to serializer
       """
           context = super(myModelViewSet, self).get_serializer_context()
           return context

C'est très stable, car chaque fois que nous demandons un groupe de vues, cela retourne également le contexte.

1
Shashank

utilisez simplement get_serializer () dans vos ensembles de vues

def get_serializer(self, *args, **kwargs):
    """
    Return the serializer instance that should be used for validating and
    deserializing input, and for serializing output.
    """
    serializer_class = self.get_serializer_class()
    kwargs['context'] = self.get_serializer_context()
    return serializer_class(*args, **kwargs)
0
steven.yan

les valeurs d'un champ de sérialiseur dépendent de l'identité de l'utilisateur actuellement connecté

Voici comment je gère de tels cas dans mon ModelViewSet:

def perform_create(self, serializer):

    user = self.request.user
    if user.username == 'myuser':
        serializer.data['myfield'] = 'something'

    serializer.save()
0
ostergaard