Django生成含UserProfile_ID变量的专属URL二维码问题排查
解决Django二维码生成引发的路径参数错误
问题核心
生成用户专属二维码时出现请求路径异常:浏览器发起了/loyalty_card/<qrcode.image.svg.SvgImage object at ...>的请求,导致视图接收的userprofile_id不是预期的数字,而是二维码对象的字符串表示,最终触发数据库查询错误:Field 'id' expected a number but got '<qrcode.image.svg.SvgImage object...>'。
错误原因
模板中直接将qrcode_img(SvgImage对象)赋值给<img>的src属性,Django渲染时会把对象转换成默认的字符串格式,浏览器将该字符串识别为相对路径,发起了错误的GET请求,导致视图接收到非法的参数值。
修复步骤
1. 修正视图:传递SVG字符串而非对象
将生成的SVG图片内容转换成字符串,传递给模板:
from io import BytesIO import qrcode from qrcode.image.svg import SvgImage @login_required def venue_loyalty_card(request, userprofile_id): # 修正查询:使用user_id匹配外键(如果UserProfile的user是外键) profile = UserProfile.objects.filter(user_id=userprofile_id) itemised_loyalty_cards = Itemised_Loyatly_Card.objects.filter(user_id=userprofile_id) factory = SvgImage stream = BytesIO() qrcode_url = f"....com/account/{userprofile_id}/" qrcode_img = qrcode.make(qrcode_url, image_factory=factory, box_size=10) qrcode_img.save(stream) # 将SVG内容读取为字符串 stream.seek(0) qrcode_svg = stream.read().decode('utf-8') return render(request, "main/account/venue_loyalty_card.html", { 'itemised_loyalty_cards': itemised_loyalty_cards, 'profile': profile, 'qrcode_url': qrcode_url, 'qrcode_svg': qrcode_svg # 传递SVG字符串 })
2. 修正模板:使用Data URI展示SVG
将<img>的src改为Data URI,直接嵌入SVG内容:
{% block content %} <br><br> Your Loyalty Cards<br> <br> <!-- 使用Data URI展示SVG --> <img style="width: 100%" src="data:image/svg+xml;utf8,{{ qrcode_svg|safe }}"> {% for userprofile in profile %} <!-- 可添加用户信息展示逻辑 --> {% endfor %} {% for itemised_loyatly_card in itemised_loyalty_cards %}<br> {% if request.user.id == itemised_loyatly_card.user.id %} Total Points: {{ itemised_loyatly_card.sum }}<br> User : {{ itemised_loyatly_card.user.id }}<br> Venue : {{ itemised_loyatly_card.venue }}<br> Add points here: {{ itemised_loyatly_card.points }}<br> {% endif %} {% endfor %} {% endblock %}
3. 修正URL配置:限制参数类型为整数
确保URL只接收数字类型的userprofile_id,避免非法请求进入视图:
path('loyalty_card/<int:userprofile_id>', views.venue_loyalty_card, name="venue-loyalty-card"),
额外优化建议
- 避免硬编码URL,使用Django的
reverse函数生成二维码指向的链接:from django.urls import reverse qrcode_url = request.build_absolute_uri(reverse('venue-loyalty-card', args=[userprofile_id])) - 如果
UserProfile是一对一关联User模型,使用get_object_or_404获取单个对象,避免空QuerySet:from django.shortcuts import get_object_or_404 profile = get_object_or_404(UserProfile, user_id=userprofile_id)
内容的提问来源于stack exchange,提问作者PhilM
相关产品推荐
相关产品推荐

