如何在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)
后端修改说明:
- 数据接收修正:用
json.loads(request.body)解析请求体,通过data.get("content")获取前端传递的扫码结果(替换原错误的"scan.content"键名) - SQL注入防护:使用参数化查询
%s传递数据,避免字符串格式化拼接SQL语句的风险 - 事务提交:添加
connection.commit()确保数据库操作生效 - 错误处理:增加JSON解析错误捕获,返回明确的状态码和提示信息
内容的提问来源于stack exchange,提问作者Jolin
相关产品推荐
相关产品推荐

