Как просмотреть профиль аутентифицированного пользователя в Django Rest Framework, используя токен

Я изучаю DRF и создаю простое приложение DRF, которое позволяет пользователю войти в систему, просмотреть профиль и обновить его. Я использую модель Django по умолчанию User и использую Knox для Token Authentication (если это можно сделать проще, используя Django Rest Authentication, пожалуйста, дайте мне знать, а также расскажите мне процедуру).

Я успешно создал API для регистрации и входа пользователя, который работает нормально, но я застрял на показе профиля аутентифицированному пользователю через токен.

У меня есть только одна модель Details, которая служит для хранения информации о профиле пользователя. У меня есть LoginSerializer, которая подключена к Login API и MainUserSerializer & UserSerializer, обе из которых подключены к User API (который действует для отображения информации о профиле на фронтенде).

Я много пробовал, искал везде, но все они показывают, как аутентифицировать пользователя с токеном через url (что-то вроде использования curl https://localhost:8000/api/user... и т.д.), postman, что-то вроде команды http post -a... в терминале и другие способы, но я не хочу тестировать или реализовывать эти способы. Мне нужно что-то, что если я открою url профиля пользователя после входа в систему с помощью ссылки localhost:8000/user, то на бэкенде это должно выглядеть так, как указано здесь введите описание ссылки здесь:

import requests

url = 'http://127.0.0.1:8000/hello/'
headers = {'Authorization': 'Token 9054f7aa9305e012b3c2300408c3dfdf390fcddf'}
r = requests.get(url, headers=headers)

Я очень старался, но мне не удается успешно перейти на страницу подробностей, аутентифицировав пользователя с помощью токена.

Мой models.py - это:

from django.db import models

# Create your models here.
from django.contrib.auth.models import User

class Detail(models.Model):
    user = models.OneToOneField(User, on_delete=models.CASCADE)
    file = models.FileField(verbose_name="CSV File", upload_to='csv_files')
    file_desc = models.TextField("CSV File Description")

    def __str__(self):
        return ("{} ({} {})".format(self.user.email, self.user.first_name, self.user.last_name))

    def __unicode__(self):
        return (self.file_desc)

Мой serializers.py - это:

from django.contrib.auth import authenticate
from django.contrib.auth.models import User
from .models import Detail
from rest_framework import serializers


class MainUserSerializer(serializers.ModelSerializer):
    class Meta:
        model = User
        fields = ('email',)


class UserSerializer(serializers.ModelSerializer):
    usr = MainUserSerializer()

    class Meta:
        model = Detail
        fields = ['usr', 'file', 'file_desc']

class LoginSerializer(serializers.Serializer):
    email = serializers.EmailField()
    password = serializers.CharField()

    def validate(self, data):
        user = authenticate(**{'username': data['email'], 'password': data['password']})
        if user and user.is_active:
            return user
        raise serializers.ValidationError('Incorrect Credentials Passed.')

Мой views.py - это:

import requests
from rest_framework import permissions
from knox.models import AuthToken
from .serializers import UserSerializer, LoginSerializer
from django.shortcuts import redirect
from rest_framework.renderers import TemplateHTMLRenderer
from rest_framework.views import APIView
from django.urls import reverse
from django.http import HttpResponseRedirect

class LoginAPIHTML(APIView):
    renderer_classes = [TemplateHTMLRenderer]
    template_name = 'accounts/login.html'

    def get(self, request):        
        serializer = LoginSerializer()
        return Response({'serializer': serializer})

    def post(self, request):
        serializer = LoginSerializer(data=request.data)
        if not serializer.is_valid():
            return Response({'serializer': serializer})
        
        user = serializer.validated_data
        url = 'http://' + str(request.get_host()) + str(reverse('user', args=None))

        headers = {
            'Authorization': 'Token ' + str(AuthToken.objects.create(user)[1])
        }

        r = requests.get(url, headers=headers, format='json')
        return HttpResponseRedirect(r)

Мой urls.py - это:

from django.urls import path, include
from .views import LoginAPIHTML

urlpatterns = [
    path('api/v1/', include('knox.urls')),
    path('login', LoginAPIHTML.as_view(), name='login'),
    path('user', UserAPI.as_view(), name='user'),
]

и ниже мой settings.py:

INSTALLED_APPS = [
    'accounts',
    'rest_framework',
    'rest_framework.authtoken',
    'knox',
    ...
]

REST_FRAMEWORK = {
    'DEFAULT_AUTHENTICATION_CLASSES': [
        'knox.auth.TokenAuthentication',
    ]
}

REST_AUTH_TOKEN_MODEL = 'knox.models.AuthToken'
REST_AUTH_TOKEN_CREATOR = 'project.apps.accounts.utils.create_knox_token'

Когда я ввожу правильные учетные данные в Login API в localhost:8000/login, то вместо перенаправления на страницу подробностей в localhost:8000/user я получаю следующую ошибку:

TypeError at /login
quote_from_bytes() expected bytes
Request Method: POST
Request URL:    http://127.0.0.1:8000/login
Django Version: 4.0.3
Exception Type: TypeError
Exception Value:    
quote_from_bytes() expected bytes

Traceback Switch to copy-and-paste view
C:\Users\Khubaib Khawar\AppData\Local\Programs\Python\Python310\lib\site-packages\django\core\handlers\exception.py, line 55, in inner
                response = get_response(request) …
Local vars
C:\Users\Khubaib Khawar\AppData\Local\Programs\Python\Python310\lib\site-packages\django\core\handlers\base.py, line 197, in _get_response
                response = wrapped_callback(request, *callback_args, **callback_kwargs) …
Local vars
C:\Users\Khubaib Khawar\AppData\Local\Programs\Python\Python310\lib\site-packages\django\views\decorators\csrf.py, line 54, in wrapped_view
        return view_func(*args, **kwargs) …
Local vars
C:\Users\Khubaib Khawar\AppData\Local\Programs\Python\Python310\lib\site-packages\django\views\generic\base.py, line 84, in view
            return self.dispatch(request, *args, **kwargs) …
Local vars
C:\Users\Khubaib Khawar\AppData\Local\Programs\Python\Python310\lib\site-packages\rest_framework\views.py, line 509, in dispatch
            response = self.handle_exception(exc) …
Local vars
C:\Users\Khubaib Khawar\AppData\Local\Programs\Python\Python310\lib\site-packages\rest_framework\views.py, line 469, in handle_exception
            self.raise_uncaught_exception(exc) …
Local vars
C:\Users\Khubaib Khawar\AppData\Local\Programs\Python\Python310\lib\site-packages\rest_framework\views.py, line 480, in raise_uncaught_exception
        raise exc …
Local vars
C:\Users\Khubaib Khawar\AppData\Local\Programs\Python\Python310\lib\site-packages\rest_framework\views.py, line 506, in dispatch
            response = handler(request, *args, **kwargs) …
Local vars
C:\Users\Khubaib Khawar\Downloads\Meistery\Round2\backend_dev_trial_ass_r2\accounts\views.py, line 202, in post
        return HttpResponseRedirect(r) …
Local vars
C:\Users\Khubaib Khawar\AppData\Local\Programs\Python\Python310\lib\site-packages\django\http\response.py, line 538, in __init__
        self["Location"] = iri_to_uri(redirect_to) …
Local vars
C:\Users\Khubaib Khawar\AppData\Local\Programs\Python\Python310\lib\site-packages\django\utils\encoding.py, line 139, in iri_to_uri
    return quote(iri, safe="/#%[]=:;$&()+,!?*@'~") …
Local vars
C:\Users\Khubaib Khawar\AppData\Local\Programs\Python\Python310\lib\urllib\parse.py, line 870, in quote
    return quote_from_bytes(string, safe) …
Local vars
C:\Users\Khubaib Khawar\AppData\Local\Programs\Python\Python310\lib\urllib\parse.py, line 895, in quote_from_bytes
        raise TypeError("quote_from_bytes() expected bytes") …
Local vars

Я сыт этим по горло. Я буду очень признателен, если кто-нибудь поможет мне настроить это либо с помощью Knox, либо с помощью Django Rest Authentication. Заранее спасибо.

Это должно помочь:

https://studygyaan.com/django/django-rest-framework-tutorial-register-login-logout

Я использую это как руководство в любое время, когда использую Knox с drf.

Просмотр журналов ошибок, которые вы опубликовали:

Local vars C:\Users\Khubaib Khawar\Downloads\Meistery\Round2\backend_dev_trial_ass_r2\accounts\views.py, line 202, in post return HttpResponseRedirect(r) …

HttpResponseRedirect ожидает url или конечную точку, на которую нужно перенаправить запрос. Но переменная r возвращает ответ от запроса GET, сделанного по адресу:

r = requests.get(url, headers=headers, format='json')

отсюда и ошибка: raise TypeError("quote_from_bytes() expected bytes") …

Я думаю, что это похоже на :

TypeError: quote_from_bytes() ожидал байт после перенаправления

Вернуться на верх