Почему моя сессия django не сохраняется? Это работает, когда я использую Postman, но не работает, когда я пытаюсь сделать это через свой Frontend

В настоящее время я работаю над компонентом регистрации для приложения, построенного с использованием React с TypeScript и Tailwind CSS, Django и MongoDB.

В моем Django backend у меня есть приложение под названием login_register_app, которое используется для функциональности регистрации. Я хочу создать сессию, которая хранит id документа при его создании, чтобы, когда пользователя попросят добавить дополнительные детали на следующей странице, можно было обновить нужный документ. На данный момент у меня есть следующая функция для регистрации:

@api_view(['POST'])
def create_login(request):
    # parse json
    body = json.loads(request.body)

    # get email and password and confirm password
    email = body.get('email')
    password = body.get('password')
    confirm_password = body.get('confirm_password')

    email_is_valid = False
    password_is_valid = False
    error = ''

    # password must be at least 8 characters and contain digit 0 - 9, Uppercase, Lowercase and Special
    # character from list (#?!@$%^&*-)
    password_validation_pattern = re.compile('^(?=.*?[A-Z])(?=.*?[a-z])(?=.*?[0-9])(?=.*?[#?!@$%^&*-]).{8,}$')

    # compare password to confirm password and regex pattern
    if password == confirm_password and re.match(password_validation_pattern, password):
        password_is_valid = True
    elif password == confirm_password:
        error = 'password is not valid. Requires at least one uppercase, lowercase, digit and special character [#?!@$%^&*-]'
    else:
        error = 'passwords do not match'
        
    # verify email does not already exist in the database
    if not users_collection.find_one({'email': email}):
        email_is_valid = True
    else:
        error = 'email already exists'


    # hash password before storing in database
    hashed_password = make_password(password)

    # save to database
    if email_is_valid and password_is_valid:
        document = users_collection.insert_one({
            'email': email,
            'password': hashed_password,
        })

        # create session to track the user id
        user_id = document.inserted_id
        request.session['user_id'] = str(user_id)
        print(request.session.items())
    

    return JsonResponse(
        {
            'emailIsValid': email_is_valid,
            'passwordIsValid': password_is_valid,
            'errorMessage': error
        }
    )

Как вы видите, после успешного создания нового документа в базе данных MongoDB создается сессия для хранения сессии под названием user_id.

В том же файле views.py у меня есть вторая функция, отвечающая за работу с дополнительной информацией, вводимой пользователем, такой как имя, дата рождения и т.д. Чтобы правильно обновить соответствующий документ, я пытаюсь получить доступ к сессии, которую я ранее создал, используя document = users_collection.find_one({"_id": bson.ObjectId(request.session['user_id'])}), как показано в коде ниже:

Однако, когда я делаю это, я получаю KeyError, предполагающий, что ключ user_id не существует в словаре сессии, но когда я проверяю словарь сессии после первоначального создания сессии, я вижу, что он там есть, как показано в стек-трассе ниже, где словарь сессии для первого вызова API (login-register/create-login/) находится в строке 1 стек-трассы, а словарь сессии для второго вызова API (login-register/core-details/) можно увидеть в строке 3 стек-трассы:

dict_items([('user_id', '63e0f975611b8440139c674c')])
[06/Feb/2023 12:58:29] "POST /login-register/create-login/ HTTP/1.1" 200 67
dict_items([])
Internal Server Error: /login-register/core-details/
Traceback (most recent call last):
  File "C:\Users\bench\Documents\GitHub\z12-performance-webapp\server\.venv\Lib\site-packages\django\core\handlers\exception.py", line 55, in inner
    response = get_response(request)
               ^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\bench\Documents\GitHub\z12-performance-webapp\server\.venv\Lib\site-packages\django\core\handlers\base.py", line 197, in _get_response
    response = wrapped_callback(request, *callback_args, **callback_kwargs)
               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\bench\Documents\GitHub\z12-performance-webapp\server\.venv\Lib\site-packages\django\views\decorators\csrf.py", line 54, in wrapped_view
    return view_func(*args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\bench\Documents\GitHub\z12-performance-webapp\server\.venv\Lib\site-packages\django\views\generic\base.py", line 103, in view  
    return self.dispatch(request, *args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\bench\Documents\GitHub\z12-performance-webapp\server\.venv\Lib\site-packages\rest_framework\views.py", line 509, in dispatch   
    response = self.handle_exception(exc)
               ^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\bench\Documents\GitHub\z12-performance-webapp\server\.venv\Lib\site-packages\rest_framework\views.py", line 469, in handle_exception
    self.raise_uncaught_exception(exc)
  File "C:\Users\bench\Documents\GitHub\z12-performance-webapp\server\.venv\Lib\site-packages\rest_framework\views.py", line 480, in raise_uncaught_exception
    raise exc
  File "C:\Users\bench\Documents\GitHub\z12-performance-webapp\server\.venv\Lib\site-packages\rest_framework\views.py", line 506, in dispatch   
    response = handler(request, *args, **kwargs)
               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\bench\Documents\GitHub\z12-performance-webapp\server\.venv\Lib\site-packages\rest_framework\decorators.py", line 50, in handler    return func(*args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\bench\Documents\GitHub\z12-performance-webapp\server\login_register_app\views.py", line 175, in add_core_user_details
    document = users_collection.find_one({"_id": bson.ObjectId(request.session['user_id'])})
                                                               ~~~~~~~~~~~~~~~^^^^^^^^^^^
  File "C:\Users\bench\Documents\GitHub\z12-performance-webapp\server\.venv\Lib\site-packages\django\contrib\sessions\backends\base.py", line 53, in __getitem__
    return self._session[key]
           ~~~~~~~~~~~~~^^^^^
KeyError: 'user_id'

Больше всего меня смущает то, что когда я тестирую эту функциональность с помощью Postman, она работает как задумано, т.е. сессия сохраняется при первом вызове API и доступна для второго вызова API, позволяя документу правильно обновляться в базе данных MongoDB. Но когда я использую свой фронтенд React, это не работает так же, как показано в приведенной выше трассировке стека. Это привело меня к первоначальному мнению, что это проблема фронтенда, однако после тестирования я убедился, что данные правильно передаются от фронтенда к бэкенду.

Кроме того, когда я проверяю базу данных через страницу /admin проекта django, я не вижу таблицы для сессий.

Любая помощь будет очень признательна!

Я считаю, что вы идете к этому неверным путем. Сессии должны отслеживаться на стороне клиента, а не на стороне сервера. После успешной регистрации/аутентификации в ответе API отправляется токен, который хранится в localStorage и используется в следующих запросах для идентификации пользователя. То, как вы делаете это сейчас, требует, чтобы ваш Django backend был stateful, что не соответствует архитектуре REST.

Вместо этого вы должны (в идеале) использовать систему аутентификации Django для регистрации пользователя, а затем отслеживать его продвижение через вашу форму на фронт-энде.

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