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

如何在Django中通过AJAX调用Python脚本及校园IoT项目优化问询

在Django中用AJAX调用Python脚本(适配你的IoT考勤支付系统)

Hey there! 针对你的场景——给非Linux用户提供友好界面替代CLI工具,我来一步步拆解怎么用AJAX结合Django实现需求,同时适配你的树莓派、RFID/指纹模块硬件架构:

核心思路

AJAX没法直接调用Python脚本,得通过Django视图作为中间层:前端页面发送AJAX请求到Django的URL,视图处理请求(调用你的Python/CLI逻辑),再把结果返回给前端。用户在网页上点个按钮就能完成操作,完全不用碰Shell。


步骤1:把CLI逻辑封装到Django视图里

别直接用subprocess调用CLI(虽然能跑,但不够优雅安全),建议把CLI的核心代码改成可导入的函数,或者写成Django管理命令,这里给两种方案:

方案A:重构CLI逻辑为可调用函数

假设你的CLI工具process_rfid_data.py里有读取RFID并同步数据库的逻辑,把它封装成函数放到Django项目里:

# 在你的Django app下新建utils/rfid_utils.py
import psycopg2
from django.conf import settings

def process_rfid(tag_id):
    # 这里写原来CLI里的核心逻辑:验证标签、更新考勤记录等
    conn = psycopg2.connect(
        dbname=settings.DATABASES['default']['NAME'],
        user=settings.DATABASES['default']['USER'],
        password=settings.DATABASES['default']['PASSWORD'],
        host=settings.DATABASES['default']['HOST']
    )
    # ... 执行数据库操作(比如插入考勤记录) ...
    conn.close()
    return {"status": "success", "message": f"RFID标签 {tag_id} 已同步"}

然后在Django视图里调用这个函数:

# views.py
from django.http import JsonResponse
from django.views.decorators.csrf import csrf_exempt  # 临时用,后面会加CSRF保护
from .utils.rfid_utils import process_rfid

@csrf_exempt
def ajax_process_rfid(request):
    if request.method == 'POST':
        tag_id = request.POST.get('tag_id')
        if not tag_id:
            return JsonResponse({"status": "error", "message": "缺少RFID标签ID"})
        # 调用封装好的业务逻辑
        result = process_rfid(tag_id)
        return JsonResponse(result)
    return JsonResponse({"status": "error", "message": "仅支持POST请求"})

方案B:直接调用现有CLI脚本(不想改代码时用)

如果暂时不想重构CLI,用subprocess调用,但一定要过滤参数避免命令注入:

# views.py
import subprocess
from django.http import JsonResponse
from django.views.decorators.csrf import csrf_exempt

@csrf_exempt
def ajax_run_cli(request):
    if request.method == 'POST':
        cmd_args = request.POST.get('args', '')
        # 安全过滤:只允许字母数字的参数(比如RFID标签ID)
        if not cmd_args.isalnum():
            return JsonResponse({"status": "error", "message": "无效参数"})
        # 调用CLI脚本
        result = subprocess.run(
            ['python', '/path/to/your/cli_tool.py', cmd_args],
            capture_output=True,
            text=True
        )
        if result.returncode == 0:
            return JsonResponse({"status": "success", "output": result.stdout})
        else:
            return JsonResponse({"status": "error", "output": result.stderr})
    return JsonResponse({"status": "error", "message": "仅支持POST请求"})

步骤2:配置Django URL路由

把上面的视图映射到一个URL,让AJAX能访问到:

# urls.py
from django.urls import path
from . import views

urlpatterns = [
    # ... 其他已有URL ...
    path('ajax/process-rfid/', views.ajax_process_rfid, name='ajax_process_rfid'),
    # 如果是调用CLI的话,加这个:
    # path('ajax/run-cli/', views.ajax_run_cli, name='ajax_run_cli'),
]

步骤3:前端编写AJAX请求(带CSRF保护)

Django默认启用CSRF保护,所以AJAX请求必须带上CSRF令牌,下面给原生JS和jQuery两种写法:

原生JS版本

<!-- 在你的Django模板页面里 -->
<button id="processRfidBtn">处理RFID数据</button>
<div id="result"></div>

<script>
// 获取CSRF令牌的工具函数
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;
}
const csrftoken = getCookie('csrftoken');

// 绑定按钮点击事件
document.getElementById('processRfidBtn').addEventListener('click', function() {
    const tagId = prompt('请输入RFID标签ID:'); // 也可以从输入框获取
    if (!tagId) return;

    fetch('/ajax/process-rfid/', {
        method: 'POST',
        headers: {
            'X-CSRFToken': csrftoken,
            'Content-Type': 'application/x-www-form-urlencoded',
        },
        body: `tag_id=${encodeURIComponent(tagId)}`
    })
    .then(response => response.json())
    .then(data => {
        const resultDiv = document.getElementById('result');
        if (data.status === 'success') {
            resultDiv.innerHTML = `<p style="color: green;">${data.message}</p>`;
        } else {
            resultDiv.innerHTML = `<p style="color: red;">${data.message}</p>`;
        }
    })
    .catch(error => {
        document.getElementById('result').innerHTML = `<p style="color: red;">请求失败:${error}</p>`;
    });
});
</script>

jQuery版本(项目用jQuery的话更简洁)

<button id="processRfidBtn">处理RFID数据</button>
<div id="result"></div>

<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
<script>
$('#processRfidBtn').click(function() {
    const tagId = prompt('请输入RFID标签ID:');
    if (!tagId) return;

    $.ajax({
        url: '{% url "ajax_process_rfid" %}', // 用Django URL反向解析,更灵活
        type: 'POST',
        data: { tag_id: tagId },
        headers: {
            'X-CSRFToken': $('[name=csrfmiddlewaretoken]').val() // 从模板表单取CSRF令牌
        },
        success: function(data) {
            if (data.status === 'success') {
                $('#result').html(`<p style="color: green;">${data.message}</p>`);
            } else {
                $('#result').html(`<p style="color: red;">${data.message}</p>`);
            }
        },
        error: function(xhr, status, error) {
            $('#result').html(`<p style="color: red;">请求失败:${error}</p>`);
        }
    });
});
</script>

针对你的IoT硬件场景的额外建议

因为你的系统用树莓派做客户端,搭配RFID/指纹模块,这里分两种常见场景给建议:

  • 场景1:树莓派采集数据后自动同步到Django:树莓派上的采集脚本可以直接用requests库发送POST请求到上面的AJAX接口,不用用户手动输入。比如树莓派上的代码:
    # 树莓派上的RFID采集脚本
    import requests
    
    rfid_tag_id = "123456"  # 从EM-18阅读器读取的标签ID
    response = requests.post(
        'https://your-django-domain.com/ajax/process-rfid/',
        data={'tag_id': rfid_tag_id},
        headers={'X-CSRFToken': 'your-csrf-token'}  # 服务器间请求可临时关闭该接口CSRF,同时加IP白名单
    )
    print(response.json())
    
  • 场景2:网页触发树莓派执行本地脚本:如果需要用户在网页上操作,让树莓派执行本地脚本(比如控制指纹模块),得在树莓派上跑个小型API服务(比如Flask),然后Django先接收AJAX请求,再转发到树莓派的API;或者用WebSocket实现实时通信,适合低延迟场景。

安全注意事项

  • 永远不要把用户输入直接拼接到subprocess命令里,一定要过滤验证参数,防止命令注入。
  • 正式环境别用@csrf_exempt,要么用上面的CSRF令牌方式,要么给特定IP(比如树莓派IP)加白名单。
  • 给AJAX接口加权限控制,比如用Django的@login_required装饰器,只允许授权用户访问。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.25 04:01:54