Django表单传递选中元素异常:邮件发送至错误收件人
问题分析
- 序号匹配错误:模板使用
forloop.counter(从1开始)命名表单隐藏字段和按钮,但视图中用enumerate的默认索引i(从0开始)匹配,导致无法正确获取trip_id,打印结果为None。 - 循环逻辑低效且易出错:遍历所有
Trip对象判断按钮点击,不仅浪费资源,还可能因数据顺序不一致导致邮件发送给错误用户。
修复方案
方案一:优化逻辑(推荐)
直接从POST数据中提取点击的按钮,获取对应行程ID后查询Trip对象发送邮件,彻底避免顺序问题:
from django.shortcuts import render, get_object_or_404 from .models import Trip from django.core.mail import EmailMessage from django.conf import settings def accept(request): trips = Trip.objects.all() z = {'aw': trips} if request.method == 'POST': # 定位被点击的操作按钮 action_key = None for key in request.POST.keys(): if key.startswith('accept_') or key.startswith('refuse_'): action_key = key break if action_key: # 提取行程序号与ID trip_num = action_key.split('_')[1] trip_id = request.POST.get(f'trip_id_{trip_num}') if trip_id: # 获取目标行程对象 trip = get_object_or_404(Trip, id=trip_id) # 组装邮件内容 if action_key.startswith('accept_'): subject = 'Trip accepted' message = 'Hi there! Your trip has been accepted.' else: subject = 'Trip refused' message = 'Hi there! Your trip has been refused.' # 发送邮件 email_msg = EmailMessage( subject, message, settings.EMAIL_HOST_USER, [trip.owner_email], ) email_msg.fail_silently = True email_msg.send() print(f"trip_id = {trip_id}") return render(request, 'system/accept.html', z)
模板代码保持不变即可,此方案通过trip_id直接查询目标行程,完全不受数据顺序影响。
方案二:仅修正序号匹配(不推荐)
如果不想大幅修改逻辑,只需让视图的序号从1开始,匹配模板的forloop.counter:
from django.shortcuts import render from .models import Trip from django.core.mail import EmailMessage from django.conf import settings def accept(request): trips = Trip.objects.all() z = {'aw': trips} if request.method == 'POST': # 让enumerate索引从1开始,匹配模板的forloop.counter for i, trip in enumerate(trips, start=1): trip_id = request.POST.get(f'trip_id_{i}') print(f"trip_id = {trip_id}") if f'accept_{i}' in request.POST: email_msg = EmailMessage( 'Trip accepted', 'Hi there! Your trip has been accepted.', settings.EMAIL_HOST_USER, [trip.owner_email], ) email_msg.fail_silently = True email_msg.send() elif f'refuse_{i}' in request.POST: email_msg = EmailMessage( 'Trip refused', 'Hi there! Your trip has been refused.', settings.EMAIL_HOST_USER, [trip.owner_email], ) email_msg.fail_silently = True email_msg.send() return render(request, 'system/accept.html', z)
原代码出错原因
- 模板生成的字段名是
trip_id_1、trip_id_2,但视图中查找的是trip_id_0、trip_id_1,完全不匹配,导致trip_id始终为None。 - 遍历所有
Trip时,若数据库存储顺序与页面渲染顺序不一致,就会出现点击第二个行程却给第一个行程所有者发邮件的问题。
内容的提问来源于stack exchange,提问作者manel DERROUAZ
相关产品推荐
相关产品推荐

