Почему моя сессия 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 для регистрации пользователя, а затем отслеживать его продвижение через вашу форму на фронт-энде.