Tivix / django-rest-auth

This app makes it extremely easy to build Django powered SPA's (Single Page App) or Mobile apps exposing all registration and authentication related functionality as CBV's (Class Base View) and REST (JSON)
www.tivix.com
MIT License
2.41k stars 661 forks source link

View is not defined, pass it as a context variable (incompatibility with current DRF) #631

Closed hanayashiki closed 4 years ago

hanayashiki commented 4 years ago

I encountered a bug using your SocialLoginView because of a recent DRF update.

As documented, I add a view called FacebookLoginView

class FacebookLoginView(SocialLoginView):
    adapter_class = FacebookOAuth2Adapter

But I got the following response:

{
    "non_field_errors": [
        "View is not defined, pass it as a context variable"
    ]
}

The exception point is here in serializer.py:

    def validate(self, attrs):
        view = self.context.get('view')
        request = self._get_request()

        if not view:
            raise serializers.ValidationError(
                _("View is not defined, pass it as a context variable")
            )

It seems that 'view' is not passed to context.

Then I find this in LoginView of views.py

    def post(self, request, *args, **kwargs):
        self.request = request
        self.serializer = self.get_serializer(data=self.request.data,
                                              context={'request': request})
        print(self.serializer)
        self.serializer.is_valid(raise_exception=True)

        self.login()
        return self.get_response()

The line

        self.serializer = self.get_serializer(data=self.request.data,
                                              context={'request': request})

is wrong, because in current version of DRF 3.11.2, get_serializer has changed its behavior

    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.setdefault('context', self.get_serializer_context())
        return serializer_class(*args, **kwargs)

If 'context' is already provided, as in LoginView.post, the new get_serializer does not override kwargs['context'] anymore, ending up not providing "view" in the context, so the api will fail.

hanayashiki commented 4 years ago

Oh, this repo is no longer maintained. Not tested, but I believe switching to https://github.com/jazzband/dj-rest-auth should solve this problem.