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

如何在Django中将JavaScript扫码的QR值传递至Python视图函数

解决二维码扫码结果通过POST存入数据库的问题

前端代码修改(添加POST请求逻辑)

在扫码事件的回调中新增发送POST请求的逻辑,将扫码结果提交到后端接口:

{% block mainbody %}

{% verbatim %}

<div id="app2" class="container">
  <head>
    <title>Instascan – Demo</title>
    <link rel="icon" type="image/png" href="favicon.png">
    <!--<link rel="stylesheet" href="../static/css/style.css">-->
    <script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/webrtc-adapter/3.3.3/adapter.min.js"></script>
    <script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.1.10/vue.min.js"></script>
    <script type="text/javascript" src="https://rawgit.com/schmich/instascan-builds/master/instascan.min.js"></script>
  </head>
  <body>
    <div id="app">
      <div class="sidebar">
        <section class="cameras">
          <h2>Cameras</h2>
          <ul>
            <li v-if="cameras.length === 0" class="empty">No cameras found</li>
            <li v-for="camera in cameras">
              <span v-if="camera.id == activeCameraId" :title="formatName(camera.name)" class="active">{{ formatName(camera.name) }}</span>
              <span v-if="camera.id != activeCameraId" :title="formatName(camera.name)">
                <a @click.stop="selectCamera(camera)">{{ formatName(camera.name) }}</a>
              </span>
            </li>
          </ul>
        </section>
        <section class="scans">
          <h2>Scans</h2>
          <ul v-if="scans.length === 0">
            <li class="empty">No scans yet</li>
          </ul>
          <transition-group name="scans" tag="ul">
            <li v-for="scan in scans" :key="scan.date" :title="scan.content">{{ scan.content }}</li>
          </transition-group>
        </section>
      </div>
      <div class="preview-container">
        <video id="preview"></video>
      </div>
    </div>
  </body>

</div>
{% endverbatim %}
{% csrf_token %} <!-- 新增:用于Django CSRF保护 -->
 
<script>
  var app = new Vue({
  el: '#app2',
  data: {
    scanner: null,
    activeCameraId: null,
    cameras: [],
    scans: []
  },

  mounted: function () {
    var self = this;
    self.scanner = new Instascan.Scanner({ video: document.getElementById('preview'), scanPeriod: 5});
    self.scanner.addListener('scan', function (content, image) {
      self.scans.unshift({ date: +(Date.now()), content: content });
      
      // 新增:发送POST请求到后端接口
      fetch('/doctor_qrscan/', { // 替换为你实际的后端路由URL
        method: 'POST',
        headers: {
          'Content-Type': 'application/json',
          // 获取CSRF令牌,适配Django默认的CSRF保护
          'X-CSRFToken': document.querySelector('input[name="csrfmiddlewaretoken"]').value
        },
        body: JSON.stringify({ content: content }) // 以content为键传递扫码结果
      })
      .then(response => response.json())
      .then(data => {
        console.log('扫码结果提交成功:', data);
      })
      .catch(error => {
        console.error('提交失败:', error);
      });
    });

    Instascan.Camera.getCameras().then(function (cameras) {
      self.cameras = cameras;
      if (cameras.length > 0) {
        self.activeCameraId = cameras[0].id;
        self.scanner.start(cameras[0]);
      } else {
        console.error('没有找到摄像头。');
      }
    }).catch(function (e) {
      console.error(e);
    });
  },

  methods: {
    formatName: function (name) {
      return name || '(未知)';
    },
    selectCamera: function (camera) {
      this.activeCameraId = camera.id;
      this.scanner.start(camera);
    }
  }
});
</script>

前端修改说明:

  • 在扫码回调中新增fetch请求,将扫码结果以JSON格式发送到后端
  • 替换fetch的URL为你在Django urls.py中配置的对应路由
  • 添加{% csrf_token %}标签并在请求头中携带CSRF令牌,适配Django默认的CSRF防护机制

后端代码修改(修复数据接收与数据库写入问题)

from django.http import JsonResponse
import json
from django.db import connection
from rest_framework.decorators import api_view

@api_view(['GET',"POST"])
def doctor_qrscan(request):
  if request.method == 'POST':
    # 解析POST请求体中的JSON数据
    try:
      data = json.loads(request.body)
      result = data.get("content")  # 对应前端发送的键名"content"
    except json.JSONDecodeError:
      return JsonResponse({"status": "error", "message": "无效的JSON数据"}, status=400)
    
    if result is not None:
      # 使用参数化查询避免SQL注入风险
      with connection.cursor() as c:
        c.execute("INSERT INTO doctor_QR (output) VALUES (%s);", [result])
        connection.commit()  # 必须提交事务,否则数据不会写入数据库
      return JsonResponse({"status": "success"})
    else:
      return JsonResponse({"status": "error", "message": "未获取到扫码内容"}, status=400)
  else:
    return JsonResponse({"status": "error", "message": "仅支持POST请求"}, status=405)

后端修改说明:

  1. 数据接收修正:用json.loads(request.body)解析请求体,通过data.get("content")获取前端传递的扫码结果(替换原错误的"scan.content"键名)
  2. SQL注入防护:使用参数化查询%s传递数据,避免字符串格式化拼接SQL语句的风险
  3. 事务提交:添加connection.commit()确保数据库操作生效
  4. 错误处理:增加JSON解析错误捕获,返回明确的状态码和提示信息

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.28 19:35:13