如何在Django中从URL生成二维码?设备添加失败问题排查
问题排查与修复方案
以下是你的代码中导致设备添加失败的关键问题,以及对应的修复方法:
1. 内存设备实例未同步数据库更新的URL
在create_url中你用filter.update()更新了数据库里的screen_url,但内存中的device实例并未同步最新值。调用create_qr时,device.screen_url还是初始空值,会导致二维码生成失败,中断整个流程。
修复方法:
直接给内存中的device对象赋值后保存,或更新数据库后重新获取实例:
def create_url(self, layout, device): screen_url = base_screen_url + device.device_id + ".html" # 直接更新内存实例并保存,替代filter.update device.screen_url = screen_url device.save() html = self.edit_device_url_html(layout, device) s3.put_object(Bucket=device_url_bucket, Key=str(device.device_id) + ".html", Body=html, ACL='public-read', ContentType='text/html', CacheControl='no-cache, no-store, must-revalidate') return device # 返回更新后的实例
调用时接收更新后的device:
device = self.create_url(empty_layout, device) self.create_qr(device)
2. 设备ID生成存在并发冲突风险
用len(Device.objects.all())计算序号,多用户同时添加设备时会生成重复的device_id,触发数据库唯一约束报错,导致添加失败。
修复方法:
改用UUID生成唯一ID,避免并发冲突:
import uuid # 替换原device_id生成逻辑 device.device_id = f"{self.random_string_generator()}-{uuid.uuid4().hex[:8]}"
3. 二维码保存路径可靠性不足
硬编码'media/' + qr_name,若media目录不存在会抛出IO错误,中断流程。应利用Django的MEDIA_ROOT配置:
from django.conf import settings import os def create_qr(self, device): if not device.screen_url: raise ValueError("设备未生成screen_url,无法生成二维码") qr_name = f'qr_{device.device_id}.png' # 确保media目录存在 media_path = settings.MEDIA_ROOT os.makedirs(media_path, exist_ok=True) qr_path = os.path.join(media_path, qr_name) qr = make(device.screen_url) qr.save(qr_path)
4. VMIscreen为true的分支未处理URL和二维码生成
当前仅在VMIscreen为false时生成URL和二维码,不符合“每个设备都需生成二维码”的需求。需补充该分支的逻辑:
if device.VMIscreen == "true": # 假设auto_create_new_layout会返回生成的layout对象 layout = self.auto_create_new_layout(request, device) device = self.create_url(layout, device) self.create_qr(device) else: empty_layout = Layout() device = self.create_url(empty_layout, device) self.create_qr(device)
5. 缺少异常捕获与错误反馈
流程中无异常捕获,任何一步出错(如用户不存在、数据库保存失败、S3上传失败)都会直接抛出异常,导致添加失败且无反馈:
def add_new_device(self, request): try: user = User.objects.get(username=request.data["username"]) device = Device() device = self.write_fields_to_object(device, request.data, user) # 用UUID生成唯一device_id import uuid device.device_id = f"{self.random_string_generator()}-{uuid.uuid4().hex[:8]}" device.save() self.set_station_data(request.data, device) if device.VMIscreen == "true": layout = self.auto_create_new_layout(request, device) device = self.create_url(layout, device) self.create_qr(device) else: empty_layout = Layout() device = self.create_url(empty_layout, device) self.create_qr(device) self.create_notification(user, device, "add", "device", "has added new Device") return "ok" except User.DoesNotExist: return "用户不存在" except Exception as e: # 记录错误日志 import logging logging.error(f"添加设备失败: {str(e)}") return f"添加失败: {str(e)}"
内容的提问来源于stack exchange,提问作者idil
相关产品推荐
相关产品推荐

