You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

登录后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",
]

问题分析与修复方案

核心问题点

  1. Session数据未主动写入:登录时调用login(request, user)仅存入用户认证标识,你需要的user_id和email并未主动写入Session;
  2. 中间件顺序异常:自定义DisableCSRF中间件放在最前面,可能干扰Session中间件的正常初始化流程;
  3. 跨域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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.18 18:57:01