Mo J. Mughrabi
Mo J. Mughrabi

Reputation: 6997

Return current user on details

I am trying to build an API view, to handle user management using django rest framework version 2.3.10 with django 1.6. I tried to build a ModelViewSet which based on the URL pk value it would return either current user or public user.

I tried to add a dispatch function which will assigned pk to current user, but it seems like this function is running too soon that its always seeing the user as anonymous

class UserViewSet(viewsets.ModelViewSet):
    """
    """
    queryset = User.objects.all()
    serializer_class = UserSerializer
    permission_classes = (IsOwnerOrCreateOnly, )

    def dispatch(self, request, *args, **kwargs):
        if kwargs.get('pk') == 'current' and not request.user.is_anonymous():
            kwargs['pk'] = request.user.pk
        resp = super(CurrentUserViewSet, self).dispatch(request, *args, **kwargs)
        return resp

I tried to do the below, which works

class UserViewSet(viewsets.ModelViewSet):
    """
    """
    queryset = User.objects.all()
    serializer_class = UserSerializer
    permission_classes = (IsOwnerOrCreateOnly, )

    def retrieve(self, request, *args, **kwargs):
        if self.kwargs.get('pk') == u'current' and not request.user.is_anonymous():
            self.kwargs['pk'] = request.user.pk
        return super(CurrentUserViewSet, self).retrieve(request, *args, **kwargs)

but, I don't want to override each and every function on several ModelViewSet classes I have, so, is there a way to use something similar to the dispatcher whereby I can check if the pk is equal to "current" and then assign current user to it?

Another question, how can I change the returned fields programmatically? for example when querying current user I want to include the first and last name from the user model, but when querying by primary key, I want first and last name to not return as response? any suggestions on how todo that?

Upvotes: 2

Views: 923

Answers (3)

anjaneyulubatta505
anjaneyulubatta505

Reputation: 11695

I got the same problem I solved it by using method "initial" instead of "dispatch"

class UserViewSet(viewsets.ModelViewSet):
    queryset = User.objects.all()
    serializer_class = UserSerializer
    permission_classes = (IsOwnerOrCreateOnly, )

    def initial(self, request, *args, **kwargs):
        # logic - code #
        if kwargs.get('pk') == 'current' and not request.user.is_anonymous():
            kwargs['pk'] = request.user.pk
        # end #
        resp = super(CurrentUserViewSet, self).initial(request, *args, **kwargs)
        return resp

see " dispatch " method in https://github.com/tomchristie/django-rest-framework/blob/master/rest_framework/views.py
for better understanding.

Upvotes: 3

cnobile
cnobile

Reputation: 433

I'm assuming that you want to save the current user to your DB model, yes?

If so this should be fairly easy to fix, just add this method to your views:

def pre_save(self, obj):
    obj.user = self.request.user

This will execute just before the model is saved. I use this all the time and it works great.

The other thing you can do is write a mixin class in a generic way that does want you want then inherit it in each of the views you need it in. Assuming that is that you have a solution that works, but just don't want to mimic you code all over the place.

Upvotes: 0

Aziz Alfoudari
Aziz Alfoudari

Reputation: 5263

Override viewsets.ModelViewSet class with your pk check implementation and use that new class, something like this:

class GenericUserViewSet(viewsets.ModelViewSet):
    def retrieve(self, request, *args, **kwargs):
        if self.kwargs.get('pk') == u'current' and not request.user.is_anonymous():
            self.kwargs['pk'] = request.user.pk
        return super(CurrentUserViewSet, self).retrieve(request, *args, **kwargs)


class UserViewSet(GenericUserViewSet):
    queryset = User.objects.all()
    serializer_class = UserSerializer
    permission_classes = (IsOwnerOrCreateOnly, )

And for the second question, perhaps creating two serializers (public and current) and changing serializer_class to either one of them in init of GenericUserViewSet may do the trick, I haven't tested this but it's an idea:

class GenericUserViewSet(viewsets.ModelViewSet):
    def __init__(self, *args, **kwargs):
        if self.kwargs.get('pk') == u'current' and not request.user.is_anonymous():
            self.serializer_class = UserSerializer
        else:
            self.serializer_class = PublicUserSerializer
        super(GenericUserViewSet, self).__init__(*args, **kwargs)

Upvotes: 0

Related Questions