4👍
This login_required
is not rest_framework
s way to authenticate. You need to use permission class for authenticating through your api if that’s what you are trying to do.
How I implemented it was, I created a view for login
class LoginView(APIView):
"""Class based view loggin in user and returning Auth Token."""
authentication_classes = [TokenAuthentication]
permission_classes = [AllowAny]
def post(self, request):
"""Check if user exists, return token if it does."""
data = JSONParser().parse(request)
serializer_obj = LoginObjectSerializer(data=data)
if serializer_obj.is_valid():
user = authenticate(username=serializer_obj.data['username'], password=serializer_obj.data['password'])
if not user:
return Response({'error': 'Invalid Credentials'}, status=404)
token, _ = Token.objects.get_or_create(user=user)
return Response({'token': token.key}, status=200)
return JsonResponse(serializer_obj.errors, status=400)
And how I authenticated my APIs was by using rest-framework
‘s provided permission classes instead of @login_required
.
My settings.py
has
REST_FRAMEWORK = {
'DEFAULT_AUTHENTICATION_CLASSES': (
'rest_framework.authentication.TokenAuthentication',
),
'DEFAULT_PERMISSION_CLASSES': (
'rest_framework.permissions.IsAuthenticated', )
}
and the permission class I used to secure my views was like this
from rest_framework.permissions import AllowAny, IsAuthenticated
authentication_classes = [TokenAuthentication]
permission_classes = [IsAuthenticated]
But I used like this in class based views. For method based, you can do this as mentioned here
@permission_classes([IsAuthenticated])
The crux of this is, you are trying to use token based authentication but you are not actually using it. Create your own login api,and use it like mentiond in this answer or the answer of @sebastienbarbier.
0👍
Your problem come from the use of the decorator @login_required
which is suppose to protect a django view.
Django views and django_rest_framework do not use the same authentication system and so need to be implemented differently.
Manual authentication
You can remove @login_required
and implement view.py
as followed :
from rest_framework.authentication import TokenAuthentication
...
@csrf_exempt
def ui_list(request):
print(request.headers)
"""
List all code user_informations, or create a new user_information.
"""
if request.method == "GET":
user_auth_tuple = TokenAuthentication().authenticate(request)
if user_auth_tuple is None:
return HttpResponse(status=401)
else:
(user, token) = user_auth_tuple # here come your user object
users = UserInformation.objects.all()
serializer = UserInformationSerializer(users, many=True)
return JsonResponse(serializer.data, safe=False)
if request.method == "POST":
...
...
But doing this process manually is really time consumming, should not be done this way as DRSF provide lots of options to make this automatic.
Class based view
What should actually be done is match a django rest framework APIView class to your model and generate a proper entry point using the permission system.
REST framework provides an APIView class, which subclasses Django’s View class.
APIView classes are different from regular View classes in the following ways:
- Requests passed to the handler methods will be REST framework’s Request instances, not Django’s HttpRequest instances.
- Handler methods may return REST framework’s Response, instead of Django’s HttpResponse. The view will manage content negotiation and setting the correct renderer on the response.
- Any APIException exceptions will be caught and mediated into appropriate responses.
- Incoming requests will be authenticated and appropriate permission and/or throttle checks will be run before dispatching the request to the handler method.
- [Django]-Django – Why doesn't syncdb respect the database router?
- [Django]-Out of range value adjusted for column warning in django when adding a large integer (11 chars)
- [Django]-Django ORM vs PostgreSQL raw SQL
0👍
REST_FRAMEWORK = {
'DEFAULT_AUTHENTICATION_CLASSES': (
'rest_framework.authentication.TokenAuthentication',
),
'DEFAULT_PERMISSION_CLASSES': (
'rest_framework.permissions.IsAuthenticated', ) }
adding rest_framework.authentication.TokenAuthentication worked
- [Django]-How to use Django QuerySet.union() in ModelAdmin.formfield_for_manytomany()?
- [Django]-Empty label in widget Select
- [Django]-Factory boy in django for non-database fields