登录后Django Session变量无法读取问题求助
问题:登录后Session在预约挂号接口中无法获取
我正在开发一个医院网站,支持患者登录并预约挂号。登录视图中打印的Session数据正常,但调用预约挂号接口时,打印的Session变量为空。
注:前端基于Next.js开发,请求已添加credentials='include',浏览器中已正常设置sessionid Cookie及对应值。
前端请求代码
const response = await fetch( "http://127.0.0.1:8000/bookings/book-appointment/", { method: "POST", headers: { "Content-Type": "application/json", }, body: JSON.stringify(appointmentData), credentials: "include" } );
Django 视图代码
@csrf_exempt def login_view(request): if request.method == 'POST': try: data = json.loads(request.body) email = data.get('email') password = data.get('password') # Fetch the user from the database user = Patient.objects.filter(email=email).first() # Check if user exists and password is correct if user and user.check_password(password): # Handle 2FA if enabled if user.enable_2fa: generate_and_send_2fa_code(user) return JsonResponse({ 'success': True, 'message': '2FA code sent', 'user_id': user.id, 'email': user.email, 'requires_2fa': True }) # Set session expiry time request.session.set_expiry(2 * 60 * 60) # 2 hours # Log the user in and save the session login(request, user) # Set a cookie for the session ID response = JsonResponse({ 'success': True, 'message': 'Login successful. Welcome!', 'user_id': user.id, 'email': user.email, 'session_id': request.session.session_key }) response.set_cookie( key='sessionid', value=request.session.session_key, max_age=2 * 60 * 60, ) request.session.save() print("Login Session data:", request.session.items()) print("Login Session ID:", request.session.session_key) return response else: return JsonResponse({'success': False, 'message': 'Invalid credentials'}) except Exception as e: return JsonResponse({'success': False, 'message': f'An error occurred: {str(e)}'}) return JsonResponse({'success': False, 'message': 'Invalid request method'}) @csrf_exempt def book_appointment(request): if request.method == 'POST': # Debugging: Print session data and session ID print("Session data:", request.session.items()) print("Session ID:", request.session.session_key) request.session.modified = True # Here try: data = json.loads(request.body) # Extract data from the session user_id = request.session.get('user_id') patient_email = request.session.get('email') if not user_id or not patient_email: return JsonResponse({'status': 'error', 'message': 'User not authenticated'}, status=401) # Extract other data from the request doctor_name = data.get('doctorName') speciality = data.get('speciality') date = data.get('date') time = data.get('time') period = data.get('period') consultation_type = data.get('consultationType') problem_description = data.get('problemDescription') patient_name = data.get('patientName') # Or use the patient's name from session doctor_image = data.get('doctor_image') # Check if the patient has already booked an appointment with the same doctor at the same time existing_appointment = Appointment.objects.filter( doctor_name=doctor_name, date=date, time=time, patient_email=patient_email ).first() if existing_appointment: return JsonResponse({ 'status': 'error', 'message': 'You already have an appointment with this doctor at this time.' }, status=400) # Check if the doctor is already booked for that time doctor_appointment = Appointment.objects.filter( doctor_name=doctor_name, date=date, time=time ).exists() if doctor_appointment: return JsonResponse({ 'status': 'error', 'message': 'The doctor is not available at this time. Please choose another time slot.' }, status=400) # Save the new appointment to the database appointment = Appointment.objects.create( doctor_name=doctor_name, speciality=speciality, date=date, time=time, period=period, consultation_type=consultation_type, problem_description=problem_description, patient_name=patient_name, # You might also use a session-stored patient name patient_email=patient_email, doctor_image=doctor_image ) return JsonResponse({ 'status': 'success', 'appointment_id': appointment.id, 'message': 'You have successfully booked an appointment!' }) except json.JSONDecodeError: return JsonResponse({'status': 'error', 'message': 'Invalid JSON'}, status=400) return JsonResponse({'status': 'error', 'message': 'Invalid request method'}, status=400)
Django 配置代码
CORS_ALLOWED_ORIGINS = [ 'http://localhost:3000', 'http://127.0.0.1:3000', ] CORS_ALLOW_CREDENTIALS = True # Application definition INSTALLED_APPS = [ "django.contrib.admin", "django.contrib.auth", "django.contrib.contenttypes", "django.contrib.sessions", "django.contrib.messages", "django.contrib.staticfiles", 'patients', 'rest_framework', 'corsheaders', 'authentication', 'allauth', 'bookAppointments', 'timelines', 'chats', 'doctorsnotes', 'medication', 'noticeboard', 'online_doctors', ] AUTH_USER_MODEL = 'authentication.User' AUTHENTICATION_BACKENDS = [ 'django.contrib.auth.backends.ModelBackend', ] SESSION_ENGINE = 'django.contrib.sessions.backends.db' SESSION_SAVE_EVERY_REQUEST = True MIDDLEWARE = [ 'patients.middleware.DisableCSRF', 'corsheaders.middleware.CorsMiddleware', "django.middleware.security.SecurityMiddleware", "django.contrib.sessions.middleware.SessionMiddleware", "django.middleware.common.CommonMiddleware", "django.middleware.csrf.CsrfViewMiddleware", "django.contrib.auth.middleware.AuthenticationMiddleware", "django.contrib.messages.middleware.MessageMiddleware", "django.middleware.clickjacking.XFrameOptionsMiddleware", ]
问题分析与修复方案
核心问题点
- Session数据未主动写入:登录时调用
login(request, user)仅存入用户认证标识,你需要的user_id和email并未主动写入Session; - 中间件顺序异常:自定义
DisableCSRF中间件放在最前面,可能干扰Session中间件的正常初始化流程; - 跨域Cookie配置缺失:缺少
SESSION_COOKIE_SAMESITE等配置,导致跨域请求中Cookie无法正确关联Session。
具体修复步骤
1. 完善登录视图的Session写入
在login(request, user)后主动存入需要的用户信息:
# 登录视图中,login(request, user)之后添加: request.session['user_id'] = user.id request.session['email'] = user.email
2. 调整中间件顺序
将自定义DisableCSRF中间件移至CsrfViewMiddleware之后,或直接移除(已使用@csrf_exempt):
MIDDLEWARE = [ 'corsheaders.middleware.CorsMiddleware', "django.middleware.security.SecurityMiddleware", "django.contrib.sessions.middleware.SessionMiddleware", "django.middleware.common.CommonMiddleware", "django.middleware.csrf.CsrfViewMiddleware", 'patients.middleware.DisableCSRF', # 调整位置或删除 "django.contrib.auth.middleware.AuthenticationMiddleware", "django.contrib.messages.middleware.MessageMiddleware", "django.middleware.clickjacking.XFrameOptionsMiddleware", ]
3. 添加跨域Cookie配置
在settings.py中补充以下配置:
# 适配跨域场景的Cookie设置 SESSION_COOKIE_SAMESITE = 'Lax' SESSION_COOKIE_DOMAIN = 'localhost' SESSION_COOKIE_HTTPONLY = True
4. 优化预约接口的认证校验
直接利用Django内置的用户认证状态,替代手动从Session取数:
# 在book_appointment视图开头添加: if not request.user.is_authenticated: return JsonResponse({'status': 'error', 'message': 'User not authenticated'}, status=401) # 直接从request.user获取用户信息: user_id = request.user.id patient_email = request.user.email
内容的提问来源于stack exchange,提问作者GILBERT KIPLANGAT
相关产品推荐
相关产品推荐

