Ошибка django UniqueConstraint в поле email (письмо для верификации sendgrid)
Я пытаюсь внедрить проверку электронной почты sendgrid в мой проект django. Я следовал руководству https://www.twilio.com/blog/send-dynamic-emails-python-twilio-sendgrid. У меня есть модели и представления, настроенные соответствующим образом, однако, я сталкиваюсь с ошибкой UniqueConstraint при попытке использовать один и тот же адрес электронной почты дважды (хотя в моей модели поле Email установлено на unique = True.
). Моя ошибка:
Exception Type: IntegrityError
Значение исключения:
UNIQUE constraint failed: newsletter_newsletteruser.email
Мой models.py:
from django.db import models
class NewsletterUser (models.Model):
email= models.EmailField(unique=True)
date_added = models.DateTimeField(auto_now_add=True)
conf_num = models.CharField(max_length=15)
confirmed = models.BooleanField(default=False)
def __str__(self):
return self.email + " (" + ("not " if not self.confirmed else "") + "confirmed)"
my admin.py
from .models import NewsletterUser, MailMessage
# Register your models here.
class NewsletterAdmin(admin.ModelAdmin):
list_display = ('email','date_added','conf_num', 'confirmed')
admin.site.register(NewsletterUser, NewsletterAdmin)
admin.site.register(MailMessage)
my views.py
from django.db.models.fields import EmailField
from django.shortcuts import render, redirect
from sendgrid.helpers.mail.bcc_email import Bcc
from django.http import HttpResponse
from .forms import NewsletterUserForm, MailMessageForm
from django.contrib import messages
from django.contrib.auth.decorators import login_required
import os
from sendgrid import SendGridAPIClient
from sendgrid.helpers.mail import Mail, Email, Content, To
from .models import NewsletterUser
from django import forms
import pandas as pd
from django.shortcuts import render
from django.http import HttpResponse
from django.conf import settings
from django.views.decorators.csrf import csrf_exempt
import random
from sendgrid import SendGridAPIClient
# Create your views here.
#!REGISTER CURRENT HOST!
host = 'http://127.0.0.1:8000/'
# Helper Functions
def random_digits():
return "%0.12d" % random.randint(0, 999999999999)
@csrf_exempt
def newsletters(request):
if request.method == 'POST':
sub = NewsletterUser(email=request.POST['email'], 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': NewsletterUserForm()})
def confirm(request):
sub = NewsletterUser.objects.get(email=request.GET['email'])
if sub.conf_num == request.GET['conf_num']:
sub.confirmed = True
sub.save()
messages.success(request, f'Dziękujemy za zapisanie adresu email do naszego newslettera!')
return render(request, 'pages/home.html' , {'email': sub.email, 'action': 'confirmed'})
my forms.py
from django import forms
from .models import NewsletterUser, MailMessage
class NewsletterUserForm (forms.ModelForm):
email = forms.EmailField(label='Twój email',
max_length=100,
widget=forms.EmailInput(attrs={'class': 'form-control'}))
class Meta:
model = NewsletterUser
fields = ['email']
Я совсем новичок в django и sendgrid, поэтому мне интересно, нужно ли мне как-то полностью переделать его, или есть какие-то шаги, которые я могу предпринять, чтобы он работал так, как описано выше. Если есть какие-то подсказки, пожалуйста, поделитесь. Спасибо
Здесь евангелист разработчиков SendGrid компании Twilio.
Я считаю, что Django здесь ведет себя так, как ожидается. Из документации Django:
Если вы попытаетесь сохранить модель с дублирующимся значением в уникальном поле, метод
django.db.IntegrityError
модели вызовет ошибкуsave()
.
Вам нужно перехватить это IntegrityError
и затем предоставить ошибку обратно пользователю.
@csrf_exempt
def newsletters(request):
if request.method == 'POST':
sub = NewsletterUser(email=request.POST['email'], conf_num=random_digits())
try:
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()})
except IntegrityError as ex:
# Return the error to your user
else:
return render(request, 'newsletter/newsletter.html', {'form': NewsletterUserForm()})
Я добавил try/except
в код выше, вам нужно будет заполнить, что делать в блоке except
, когда email не уникален.