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

Django+Ngrok环境下JS前端POST请求异常及跨网连接失败问题

问题描述

我用Python Django开发Web服务,部署前用Ngrok做测试,遇到三个问题:

  • 前端JS发送的POST请求在部分接口拿不到数据,返回None,Django日志和浏览器都显示响应200 OK,但日志里没数据输出
  • 跨网访问时所有请求都报CONNECTION_REFUSED错误
  • 表单提交的POST请求正常,但JS发的不行,已经按文档配置corsheaders中间件但没用

JS POST请求代码

const url = "http://localhost:8000/register_equipment/";

const data = {
    "product": inputProduct.value,
    "description": inputDescription.value,
    "serial": inputSerial.value,
    "warehouse_location": inputWarehouseLocation.value,
    "shelf_location": inputShelfLocation.value,
    "additional_location": inputAdditionalLocation.value,
    "observations": inputObservations.value,
    "quantity": inputQuantity.value,
    "dedicated": dedicatedValues
};

// Request configuration
const options = {
    method: 'POST',
    mode: 'cors',
    headers: {
        'Content-Type': 'application/json',
        'X-CSRFToken': getCookie('csrftoken') // Add CSRF token header
    },
    body: JSON.stringify(data)
};

// Perform the request using fetch
fetch(url, options)
    .then(response => {
        if (response.ok) {
            return response.json(); // Convert the response to JSON
        }
        throw new Error('Request failed');
    })
    .then(responseData => {
        console.log(responseData.groups); // Handle response data
    })
    .catch(error => {
        console.error('Error fetching group list:', error); // Handle errors
    });

获取CSRF Token的函数

function getCookie(name) {
    let cookieValue = null;
    if (document.cookie && document.cookie !== '') {
        const cookies = document.cookie.split(';');
        for (let i = 0; i < cookies.length; i++) {
            const cookie = cookies[i].trim();
            if (cookie.substring(0, name.length + 1) === (name + '=')) {
                cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
                break;
            }
        }
    }
    return cookieValue;
}

Django视图代码

@csrf_exempt
def register_equipment(request):
    if not request.user.is_authenticated:
        return redirect('login')
    
    if request.method == 'POST':
        # Get JSON data from the frontend
        data = json.loads(request.body)
        print(data)
        print(data.get("dedicated"))

        # Process location data
        location = {
            "warehouse": data.get("warehouse_location"),
            "shelf": data.get("shelf_location"),
            "additional": data.get("additional_location"),
        }

        # Process incoming data and save the equipment
        try:
            new_equipment = Equipment(
                product=data.get("product"),
                description=data.get("description"),
                serial=data.get("serial"),
                location=location,
                observations=data.get("observations"),
                dedicated=data.get("dedicated"),
                quantity=data.get("quantity"),
                available=True
            )
            new_equipment.save()
            response_data = {'message': 'Equipment registered successfully'}
            return JsonResponse(response_data)

        except KeyError:
            return JsonResponse({'error': 'Missing required data'}, status=400)
    
    return JsonResponse({'error': 'Failed to register equipment'}, status=400)

CORS配置

INSTALLED_APPS = [
    ...
    "corsheaders",  
    ...
]

MIDDLEWARE = [
    ...
    "corsheaders.middleware.CorsMiddleware",
    ...
]

正常工作的表单代码

<form method="post">
    {% csrf_token %}
    <div class="form-group">
        <label for="username">Nombre de usuario:</label>
        <input type="text" class="form-control" name="username" id="username" required>
    </div>
    <div class="form-group">
        <label for="password">Contraseña:</label>
        <input type="password" class="form-control" name="password" id="password" required>
    </div>
    <button type="submit" class="btn btn-primary btn-block">Iniciar sesión</button>
                            
</form>
解决方案

问题1:JS POST请求返回None,日志无数据输出

  • 排查前端输入值:在fetch前添加console.log(data),确认inputProduct.value等DOM元素是否正确获取、字段值是否为空。如果某个输入元素未找到,对应字段会是undefined,JSON序列化后变成null。
  • 完善视图异常捕获:当前仅捕获KeyError,但json.loads(request.body)可能抛出JSONDecodeError(比如前端JSON格式错误),导致打印逻辑被跳过。修改视图代码:
from django.http import JsonResponse
import json
from json.decoder import JSONDecodeError

@csrf_exempt
def register_equipment(request):
    if not request.user.is_authenticated:
        return redirect('login')
    
    if request.method == 'POST':
        try:
            data = json.loads(request.body)
            print(data)
            print(data.get("dedicated"))

            location = {
                "warehouse": data.get("warehouse_location"),
                "shelf": data.get("shelf_location"),
                "additional": data.get("additional_location"),
            }

            new_equipment = Equipment(
                product=data.get("product"),
                description=data.get("description"),
                serial=data.get("serial"),
                location=location,
                observations=data.get("observations"),
                dedicated=data.get("dedicated"),
                quantity=data.get("quantity"),
                available=True
            )
            new_equipment.save()
            response_data = {'message': 'Equipment registered successfully'}
            return JsonResponse(response_data)

        except JSONDecodeError:
            return JsonResponse({'error': 'Invalid JSON format'}, status=400)
        except KeyError as e:
            return JsonResponse({'error': f'Missing required data: {str(e)}'}, status=400)
    
    return JsonResponse({'error': 'Failed to register equipment'}, status=400)
  • 检查dedicatedValues类型:如果是数组或复杂对象,确认Django的Equipment模型中dedicated字段是否为JSONField,否则无法正常存储。

问题2:跨网访问报CONNECTION_REFUSED错误

  • 替换请求URL:前端必须使用Ngrok提供的公网域名,比如Ngrok生成的https://abc123.ngrok.io,将JS中的url改为"https://abc123.ngrok.io/register_equipment/"。
  • 允许Django服务外部访问:启动开发服务器时执行python manage.py runserver 0.0.0.0:8000,默认的localhost:8000仅允许本地访问,Ngrok无法转发请求。

问题3:JS POST请求无效,CORS配置不生效

  • 完善CORS配置:在settings.py中补充以下配置:
# 测试环境可临时允许所有域名,生产环境需指定具体域名
CORS_ALLOW_ALL_ORIGINS = True
CORS_ALLOW_CREDENTIALS = True

# 生产环境示例:
# CORS_ALLOWED_ORIGINS = [
#     "https://your-ngrok-domain.ngrok.io",
#     "http://localhost:3000",
# ]
  • 调整中间件顺序:CorsMiddleware必须放在CommonMiddleware之前,否则CORS头无法正确设置:
MIDDLEWARE = [
    "corsheaders.middleware.CorsMiddleware",
    "django.middleware.common.CommonMiddleware",
    # 其他中间件...
]
  • 优化CSRF Cookie设置:使用Ngrok的HTTPS时,需在settings.py中添加:
CSRF_COOKIE_SAMESITE = 'Lax'
SESSION_COOKIE_SAMESITE = 'Lax'
CSRF_COOKIE_SECURE = True
SESSION_COOKIE_SECURE = True
  • 生产环境建议移除@csrf_exempt,确保CSRF保护生效。

内容的提问来源于stack exchange,提问作者mrdonbello

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.15 12:42:03