2015-04-08 12 views
6

Sto lavorando a un progetto usando django-rest-framework. Nella mia vista API, un utente autenticato può creare altri utenti. Ma solo cinque. Quindi se ci sono cinque utenti registrati da un utente, desidero inviarlo nella risposta che ha raggiunto il limite. Quindi, ho bisogno di ottenere sul mio serializzatore l'utente autenticato ma, non riesco a trovare un modo per passarlo dal mio ModelViewSet al mio serializzatore.Come ottenere l'utente autenticato sulla classe serializzatore per la convalida

Questo è il mio codice:

Vista:

class ChildUserViewSet(viewsets.ModelViewSet): 
    serializer_class = ChildUserSerializer 
    queryset = User.objects.all() 

    authentication_classes = (
     TokenAuthentication, 
    ) 
    permission_classes = (
     IsAuthenticated, 
    ) 

    def perform_create(self, serializer): 
     account_group = self.request.user.userprofile.get_account_group 

     mobile_number = serializer.data.get('mobile_number') 
     password = serializer.data.get('password') 
     user = serializer.save() 
     user.set_password(password) 
     user.save() 

     # Generate user profile 
     UserProfile.objects.create(
      user=user, 
      mobile_number=mobile_number, 
      user_type=CHILD, 
      related_account_group=account_group, 
     ) 

Serializer:

class ChildUserSerializer(serializers.ModelSerializer): 
    mobile_number = serializers.CharField() 

    class Meta: 
     model = User 

     fields = (
      'first_name', 
      'last_name', 
      'email', 
      'password', 
      'mobile_number', 
     ) 

    def validate(self, data): 
     """ 
     Check that the start is before the stop. 
     """ 
     # Get authenticated user for raise hit limit validation 



    def validate_email(self, value): 
     if User.objects.filter(email=value): 
      raise serializers.ValidationError("This field must be unique.") 
     return value 

    def create(self, validated_data): 
     username = generate_unique_username(
      u'{0}{1}'.format(
       validated_data['first_name'], 
       validated_data['last_name'], 
      ) 
     ) 

     user = User(
      username=username, 
      first_name=validated_data['first_name'], 
      last_name=validated_data['last_name'], 
      email=validated_data['email'], 
     ) 

     user.set_password(validated_data['password']) 
     user.save() 

     return user 

Poi, nella funzione def validate(self, data) della mia serializzatore, voglio ottenere l'utente attualmente autenticato.

Come posso passare request.user dalla mia APIView al mio serializzatore?

risposta

8

Ho trovato un modo ancora più semplice per realizzare questo! Si scopre che la classe GenericAPIView di base del Resto quadro (da cui tutti i generici View classi di Riposo Framework discendere) includes a function called get_serializer_context():

def get_serializer_context(self): 
    """ 
    Extra context provided to the serializer class. 
    """ 
    return { 
     'request': self.request, 
     'format': self.format_kwarg, 
     'view': self 
    } 

Come si può vedere, la tornata context oggetto contiene lo stesso request oggetto che la vista riceve. Questo oggetto viene quindi impostare when the serializer is initialized:

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) 

Così per accedere l'utente che ha effettuato la richiesta, è sufficiente chiamare self.context['request'].user dalla funzione del vostro Serializer validate_:

class TemplateSerializer(serializers.ModelSerializer): 
    def validate_parent(self, value): 
     print(self.context['request'].user) 

     return value 

    class Meta: 
     model = Template 

E la parte migliore è che non c'è bisogno di ignorare qualsiasi cosa nella vostra ModelViewSet, essi possono rimanere semplice come si desidera:

class TemplateViewSet(viewsets.ModelViewSet): 
    serializer_class = TemplateSerializer 
    permission_classes = [IsAdmin] 
3

È possibile passare un contesto aggiuntivo al serializzatore con serializer = ChildUserSerializer(data, context={'request': request}). È quindi possibile accedere all'utente autenticato tramite request.user all'interno del metodo di convalida del serializzatore.

1

Nel vostro punto di vista quando si inizializza serializzatore come

serializer = ChildUserSerializer(data=request.DATA,context={'request':request})

, inviare un contesto che contiene request.Then in Serializzatori all'interno la funzione di chiamata

request=self.context['request']

Poi si può accedere request.user.

2

In djangorestframework> 3.2.4 la classe rest_framework.generic.GenericAPIView include la richiesta http per impostazione predefinita nel contesto serializzatore.

Così all'interno del vostro serializzatore è possibile accedervi da: self.context['request'] e l'utente self.context['request'].user

Così il vostro ChildUserSerializer sarà simile:

class ChildUserSerializer(serializers.ModelSerializer): 
    mobile_number = serializers.CharField() 
    .... 
    def validate(self, data): 
     """ 
     Check that the start is before the stop. 
     """ 
     # Get authenticated user for raise hit limit validation 
     user = self.context['request'].user 
     # do something with the user here 
    def validate_email(self, value): 
     if User.objects.filter(email=value): 
      raise serializers.ValidationError("This field must be unique.") 
     return value 
    ... 
Problemi correlati