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

Django集成SendGrid邮件验证时邮箱UniqueConstraint错误解决求助

问题根因

你定义的NewsletterUserForm作为ModelForm已经继承了模型email字段的unique=True校验规则,但你的视图逻辑完全没有使用表单做校验,直接从request.POST中取邮箱构造模型实例保存,重复邮箱直接触发了数据库层面的唯一约束报错。

修复步骤

1. 修改views.py中的newsletters视图逻辑

替换原有的POST处理逻辑,先走表单校验,校验通过后再保存数据、发送邮件,校验失败会自动把错误信息带回模板展示:

@csrf_exempt
def newsletters(request):
    if request.method == 'POST':
        # 实例化表单,把POST数据传入
        form = NewsletterUserForm(request.POST)
        # 触发表单校验,包含邮箱唯一性校验
        if form.is_valid():
            # 校验通过后构造模型实例,不直接提交到数据库
            sub = form.save(commit=False)
            sub.conf_num = random_digits()
            sub.save()
            # 后面的发送邮件逻辑保持不变
            message = Mail(
                from_email='pasiekaradosc@gmail.com',
                to_emails=sub.email,
                subject='Potwierdzenie Adresu Email w Newsletterze Pasieka Radość',
                html_content= "<h1>Dziękujemy za zapisanie się do newslettera Pasieka Radość!<h1> \<h2>Aby potwierdzić rejestrację newslettera</h2> \<h2><a href='{}confirm/?email={}&conf_num={}'> Kliknij w poniższy link</a>.<h2>".format(request.build_absolute_uri(host),
                                                        sub.email,
                                                        sub.conf_num))
            sg = SendGridAPIClient(os.environ.get('SENDGRID_API_KEY'))
            response = sg.send(message)
            return render(request, 'newsletter/newsletter.html', {'email': sub.email, 'action': 'wysłano', 'form': NewsletterUserForm()})
        else:
            # 校验不通过,把带错误信息的表单传回模板
            return render(request, 'newsletter/newsletter.html', {'form': form})
    else:
        return render(request, 'newsletter/newsletter.html', {'form': NewsletterUserForm()})

2. (可选)自定义邮箱重复的错误提示

在forms.py中修改字段定义,添加自定义错误信息,展示更友好:

class NewsletterUserForm (forms.ModelForm):
    email = forms.EmailField(
        label='Twój email',
        max_length=100,
        widget=forms.EmailInput(attrs={'class': 'form-control'}),
        # 自定义错误提示
        error_messages={'unique': '该邮箱已经订阅过我们的通讯了'}
    )
    
    class Meta:
        model = NewsletterUser
        fields = ['email']

3. 模板无需修改

你已经使用了crispy_forms渲染表单,表单校验失败后会自动在输入框下方展示错误提示,不会再抛出数据库异常。

可选优化

如果需要支持用户重复提交未验证的邮箱时重发验证邮件,可以在校验到邮箱已存在时,判断对应的confirmed字段状态,如果是未验证,就更新验证码重新发邮件,无需提示重复。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.01 11:24:04