django“重复的键值违反了唯一约束”主键
我从我写的表格中发现了一些非常奇怪的错误。
使用: postgres 8.4 ubuntu 10.04 奥桑2.6 django 1.2.4
基本上我有一个收集姓名和电子邮件地址的表单。但我需要在另外两个表中创建虚拟行,以便我们可以跟踪它们。型号如下。
from django.db import models
from django.contrib.auth.models import User
from django.core.urlresolvers import reverse
from django.contrib.sites.models import Site
# Create your models here.
class company(models.Model):
company = models.CharField(max_length=100)
address = models.CharField(max_length=300)
street = models.CharField(max_length=200)
suburb = models.CharField(max_length=100)
phone_number = models.CharField(max_length=15)
contact_person = models.CharField(max_length=50,null=True)
email = models.EmailField(max_length=100, null=True)
latitude = models.CharField(max_length=10, null=True)
longitude = models.CharField(max_length=11, null=True)
def __unicode__(self):
return unicode(self.company) + " - " + unicode(self.address) + " - " + unicode(self.contact_person) + " - " + unicode(self.email)
class campaign(models.Model):
campaign_name = models.CharField(max_length=20)
description = models.TextField(max_length=200)
start_date = models.DateField(null=True)
end_date = models.DateField(null=True)
spent = models.DecimalField(decimal_places=2, max_digits=6)
def __unicode__(self):
return self.campaign_name
class contact_date(models.Model):
CONTACT_CHOICES = (
('email', 'email'),
('person', 'person'),
('twitter', 'twitter'),
('facebook', 'facebook'),
('Newsletter', 'Newsletter'),
)
contacted = models.DateField()
who = models.ForeignKey(User)
how = models.CharField(max_length=15, choices=CONTACT_CHOICES)
company = models.ForeignKey(company)
campaign = models.ForeignKey(campaign)
def __unicode__(self):
return unicode(self.company) + " - " + unicode(self.contacted) + " - " + self.how + " - " + unicode(self.campaign)
class questionaire_1(models.Model):
SECTOR_CHOICES = (
('x', ''),
('0', 'Medical'),
('1', 'Vet'),
('2', 'Hair Dresser'),
('3', 'Beauty Salon'),
('4', 'Hospitality'),
('5', 'Retail'),
('6', 'Other')
)
IMPORTANCE_CHOICES = (
('x', ''),
('0', 'Very Important'),
('1', 'Important'),
('2', 'Moderately Important'),
('3', 'Not That Important'),
('4', 'Not at all important')
)
ROYALTIES_CHOICES = (
('x', ''),
('0', 'no-I didnt know about them'),
('1', 'no-but would like to'),
('2', 'Yes'),
('3', 'No, don\'t want to')
)
SPEND_CHOICES = (
('x', ''),
('0', '$1000 or more'),
('1', '$500 or $1000'),
('2', '$200 to $500'),
('3', 'don\'t know'),
('4', 'Nothing')
)
INTERNET_CHOICES = (
('x', ''),
('0', 'Yes'),
('5', 'No')
)
INTERESTED_CHOICES = (
('x', ''),
('0', 'Yes'),
('20', 'No')
)
USEDNOW_CHOICES = (
('x', ''),
('Radio', 'Radio'),
('Ipod', 'ipod'),
('Streaming Radio', 'Streaming Radio'),
('CDs', 'CDs')
)
contact = models.ForeignKey(contact_date)
sector = models.CharField(max_length=1, choices=SECTOR_CHOICES, null=True)
importance = models.CharField(max_length=1, choices=IMPORTANCE_CHOICES, null=True)
royalties = models.CharField(max_length=1, choices=ROYALTIES_CHOICES, null=True)
spend = models.CharField(max_length=1, choices=SPEND_CHOICES, null=True)
internet = models.CharField(max_length=1, choices=INTERNET_CHOICES, null=True)
use_now = models.CharField(max_length=20, choices=USEDNOW_CHOICES, null=True)
interested = models.CharField(max_length=2, choices=INTERESTED_CHOICES, null=True)
score = models.IntegerField(null=True)
comments = models.TextField(max_length=500, null=True)
def calculate_score(self):
if (self.sector == 'x') or (self.importance == 'x') or (self.royalties == 'x') or (self.spend == 'x') or (self.internet == 'x') or (self.interested == 'x'):
self.sector = None
self.importance = None
self.royalties = None
self.spend = None
self.internet = None
self.interested = None
return None
else:
return int(self.sector) + int(self.importance) + int(self.royalties) + int(self.spend) + int(self.internet) + int(self.interested)
def save(self, *args, **kwargs):
self.score = self.calculate_score()
super(questionaire_1, self).save(*args, **kwargs)
def __unicode__(self):
return unicode(self.contact)
class firstEmail(models.Model):
contact = models.ForeignKey(contact_date)
emailSent = models.BooleanField(default=False)
whoTo = models.CharField(max_length = 50)
MoreInformation = models.BooleanField(default=False)
emailLink = models.CharField(max_length=75, null=True)
comments = models.TextField(max_length=500, null=True)
def constructEmailLink(self):
return "infra.inthebackground.com" + reverse('inthebackgroundSite.marketing.views.confirm', args=[self.id])
#watch out for potential DB hits on this one, as we are potentially saving twice.
def save(self, *args, **kwargs):
super(firstEmail, self).save(*args, **kwargs)
self.emailLink = self.constructEmailLink()
super(firstEmail, self).save(*args, **kwargs)
我的观点
# Create your views here.
from django.shortcuts import render_to_response, get_list_or_404, get_object_or_404
from django.http import HttpResponse, HttpResponseRedirect
from inthebackgroundSite.marketing.models import campaign, company, contact_date, questionaire_1, firstEmail
from inthebackgroundSite.marketing.forms import AddNewEmailForm
from django.contrib.auth.models import User
from django.views.decorators.csrf import csrf_protect
from django.template import RequestContext
from django.core.urlresolvers import reverse
from django.contrib.auth.decorators import login_required
#######################################################
# view all details of contacts and their Questionaires
#
#######################################################
@ login_required
def viewAllDetails(request, contact_id):
contactDetails = get_list_or_404(contact_date, id=contact_id)
questionaireDetails = list(questionaire_1.objects.filter(contact=contact_id))
firstEmailDetails = list(firstEmail.objects.filter(contact=contact_id))
return render_to_response('marketing/viewAllDetails.html',
{'contactDetails' : contactDetails, 'questionaireDetails' : questionaireDetails, 'firstEmailDetails' : firstEmailDetails})
#######################################################
# Takes a confirmation from the user that they are
# replying on behalf of a company. then submits a form
# that triggers emailMeAtLaunch()
#
#######################################################
@csrf_protect
d ef confirm(request,firstEmail_id):
firstEmailDetails = get_object_or_404(firstEmail, id=firstEmail_id)
contactDetails = get_object_or_404(contact_date, id=firstEmailDetails.contact.id)
companyDetails = get_object_or_404(company, id=contactDetails.company.id)
campaignDetails = get_object_or_404(campaign, id=contactDetails.campaign.id)
UserDetails = get_object_or_404(User, id=1)
return render_to_response('marketing/confirm.html', {'firstEmailDetails': firstEmailDetails, 'companyDetails' : companyDetails}, context_instance=RequestContext(request))
########################################################
# This view updates the firstEmail table specified by the
# id passed in, setting MoreInformation to true.
#
########################################################
def emailMeAtLaunch(request,firstEmail_id):
firstEmailDetails = get_object_or_404(firstEmail, id=firstEmail_id)
contactDetails = get_object_or_404(contact_date, id=firstEmailDetails.contact.id)
companyDetails = get_object_or_404(company, id=contactDetails.company.id)
firstEmailDetails.MoreInformation = True
firstEmailDetails.save()
return render_to_response('marketing/thankyou.html', {'firstEmailDetails': firstEmailDetails, 'companyDetails' : companyDetails}, context_instance=RequestContext(request))
@csrf_protect
def addMeToMailingList(request):
if request.method == 'POST':
form = AddNewEmailForm(request.POST)
if form.is_valid():
form.save()
return HttpResponseRedirect(reverse('inthebackgroundSite.marketing.views.thankyou'))
else:
#print "not POST method"
form = AddNewEmailForm()
return render_to_response('marketing/addToMailingList.html', {'form': form }, context_instance=RequestContext(request))
def thankyou(request):
return render_to_response('marketing/thankyou.html')
和最后我的表格(对所有代码感到抱歉......)
import datetime
from django import forms
from inthebackgroundSite.marketing.models import campaign, company, contact_date, firstEmail
from django.db import transaction
from django.template import RequestContext
from django.shortcuts import render_to_response, get_list_or_404, get_object_or_404
from django.contrib.auth import authenticate
from django.contrib.auth.models import User
class AddNewEmailForm(forms.Form):
ContactPerson = forms.CharField(max_length=200)
email = forms.EmailField()
#def __init__(self, *args, **kwargs):
# self.firstEmail_id = kwargs.pop('firstEmail_id', None)
#@transaction.commit_on_success
def save(self):
now = datetime.date.today()
UserDetails = get_object_or_404(User, id=1)
campaignDetails = get_object_or_404(campaign, id=1)
#orginalFirstEmail = get_object_or_404(firstEmail, id=self.firstEmail_id)
#originalContact = get_object_or_404(contact_date, id=orginalFirstEmail.contact.id)
#originalCompany = get_object_or_404(company, id=originalContact.company.id)
newCompany = company.objects.create(company = "unknown",
address = "unknown",
street = "unknown",
suburb = "unknown",
phone_number = "unknown",
contact_person = self.cleaned_data['ContactPerson'],
email = self.cleaned_data['email'],
latitude = None,
longitude = None
)
print str(newCompany.id) + ": " + unicode(newCompany)
newContact = contact_date.objects.create(contacted = now,
who = UserDetails,
how = 'email',
company = newCompany,
campaign = campaignDetails
)
print str(newContact.id) + ": " + unicode(newContact)
newFirstEmail = firstEmail.objects.create(contact = newContact,
emailSent = False,
whoTo = "unknown",
MoreInformation = True,
comments = "This is a new addition to the mailing list that came from an unknown company.\n The company that this email was sent to is in the WhoTo",
)
print str(newFirstEmail.id) + ": " + unicode(newFirstEmail)
我得到的问题是
重复的键值违反了唯一约束“marketing_firstemail_pkey”
现在通常如果我直接将数据加载到postgres并且没有更新序列,这个问题就会出现对于 ID。但我在这个表中没有任何数据......没有!我仍然收到此错误..我不明白这是怎么发生的。
任何帮助都会很棒!
Im getting some really weird errors coming out of a form i wrote.
using:
postgres 8.4
ubuntu 10.04
oython 2.6
django 1.2.4
Basically I have an form that collects a name and an email address. But I need to make dummy rows in two other tables so we can track them. Models below.
from django.db import models
from django.contrib.auth.models import User
from django.core.urlresolvers import reverse
from django.contrib.sites.models import Site
# Create your models here.
class company(models.Model):
company = models.CharField(max_length=100)
address = models.CharField(max_length=300)
street = models.CharField(max_length=200)
suburb = models.CharField(max_length=100)
phone_number = models.CharField(max_length=15)
contact_person = models.CharField(max_length=50,null=True)
email = models.EmailField(max_length=100, null=True)
latitude = models.CharField(max_length=10, null=True)
longitude = models.CharField(max_length=11, null=True)
def __unicode__(self):
return unicode(self.company) + " - " + unicode(self.address) + " - " + unicode(self.contact_person) + " - " + unicode(self.email)
class campaign(models.Model):
campaign_name = models.CharField(max_length=20)
description = models.TextField(max_length=200)
start_date = models.DateField(null=True)
end_date = models.DateField(null=True)
spent = models.DecimalField(decimal_places=2, max_digits=6)
def __unicode__(self):
return self.campaign_name
class contact_date(models.Model):
CONTACT_CHOICES = (
('email', 'email'),
('person', 'person'),
('twitter', 'twitter'),
('facebook', 'facebook'),
('Newsletter', 'Newsletter'),
)
contacted = models.DateField()
who = models.ForeignKey(User)
how = models.CharField(max_length=15, choices=CONTACT_CHOICES)
company = models.ForeignKey(company)
campaign = models.ForeignKey(campaign)
def __unicode__(self):
return unicode(self.company) + " - " + unicode(self.contacted) + " - " + self.how + " - " + unicode(self.campaign)
class questionaire_1(models.Model):
SECTOR_CHOICES = (
('x', ''),
('0', 'Medical'),
('1', 'Vet'),
('2', 'Hair Dresser'),
('3', 'Beauty Salon'),
('4', 'Hospitality'),
('5', 'Retail'),
('6', 'Other')
)
IMPORTANCE_CHOICES = (
('x', ''),
('0', 'Very Important'),
('1', 'Important'),
('2', 'Moderately Important'),
('3', 'Not That Important'),
('4', 'Not at all important')
)
ROYALTIES_CHOICES = (
('x', ''),
('0', 'no-I didnt know about them'),
('1', 'no-but would like to'),
('2', 'Yes'),
('3', 'No, don\'t want to')
)
SPEND_CHOICES = (
('x', ''),
('0', '$1000 or more'),
('1', '$500 or $1000'),
('2', '$200 to $500'),
('3', 'don\'t know'),
('4', 'Nothing')
)
INTERNET_CHOICES = (
('x', ''),
('0', 'Yes'),
('5', 'No')
)
INTERESTED_CHOICES = (
('x', ''),
('0', 'Yes'),
('20', 'No')
)
USEDNOW_CHOICES = (
('x', ''),
('Radio', 'Radio'),
('Ipod', 'ipod'),
('Streaming Radio', 'Streaming Radio'),
('CDs', 'CDs')
)
contact = models.ForeignKey(contact_date)
sector = models.CharField(max_length=1, choices=SECTOR_CHOICES, null=True)
importance = models.CharField(max_length=1, choices=IMPORTANCE_CHOICES, null=True)
royalties = models.CharField(max_length=1, choices=ROYALTIES_CHOICES, null=True)
spend = models.CharField(max_length=1, choices=SPEND_CHOICES, null=True)
internet = models.CharField(max_length=1, choices=INTERNET_CHOICES, null=True)
use_now = models.CharField(max_length=20, choices=USEDNOW_CHOICES, null=True)
interested = models.CharField(max_length=2, choices=INTERESTED_CHOICES, null=True)
score = models.IntegerField(null=True)
comments = models.TextField(max_length=500, null=True)
def calculate_score(self):
if (self.sector == 'x') or (self.importance == 'x') or (self.royalties == 'x') or (self.spend == 'x') or (self.internet == 'x') or (self.interested == 'x'):
self.sector = None
self.importance = None
self.royalties = None
self.spend = None
self.internet = None
self.interested = None
return None
else:
return int(self.sector) + int(self.importance) + int(self.royalties) + int(self.spend) + int(self.internet) + int(self.interested)
def save(self, *args, **kwargs):
self.score = self.calculate_score()
super(questionaire_1, self).save(*args, **kwargs)
def __unicode__(self):
return unicode(self.contact)
class firstEmail(models.Model):
contact = models.ForeignKey(contact_date)
emailSent = models.BooleanField(default=False)
whoTo = models.CharField(max_length = 50)
MoreInformation = models.BooleanField(default=False)
emailLink = models.CharField(max_length=75, null=True)
comments = models.TextField(max_length=500, null=True)
def constructEmailLink(self):
return "infra.inthebackground.com" + reverse('inthebackgroundSite.marketing.views.confirm', args=[self.id])
#watch out for potential DB hits on this one, as we are potentially saving twice.
def save(self, *args, **kwargs):
super(firstEmail, self).save(*args, **kwargs)
self.emailLink = self.constructEmailLink()
super(firstEmail, self).save(*args, **kwargs)
my views
# Create your views here.
from django.shortcuts import render_to_response, get_list_or_404, get_object_or_404
from django.http import HttpResponse, HttpResponseRedirect
from inthebackgroundSite.marketing.models import campaign, company, contact_date, questionaire_1, firstEmail
from inthebackgroundSite.marketing.forms import AddNewEmailForm
from django.contrib.auth.models import User
from django.views.decorators.csrf import csrf_protect
from django.template import RequestContext
from django.core.urlresolvers import reverse
from django.contrib.auth.decorators import login_required
#######################################################
# view all details of contacts and their Questionaires
#
#######################################################
@ login_required
def viewAllDetails(request, contact_id):
contactDetails = get_list_or_404(contact_date, id=contact_id)
questionaireDetails = list(questionaire_1.objects.filter(contact=contact_id))
firstEmailDetails = list(firstEmail.objects.filter(contact=contact_id))
return render_to_response('marketing/viewAllDetails.html',
{'contactDetails' : contactDetails, 'questionaireDetails' : questionaireDetails, 'firstEmailDetails' : firstEmailDetails})
#######################################################
# Takes a confirmation from the user that they are
# replying on behalf of a company. then submits a form
# that triggers emailMeAtLaunch()
#
#######################################################
@csrf_protect
d ef confirm(request,firstEmail_id):
firstEmailDetails = get_object_or_404(firstEmail, id=firstEmail_id)
contactDetails = get_object_or_404(contact_date, id=firstEmailDetails.contact.id)
companyDetails = get_object_or_404(company, id=contactDetails.company.id)
campaignDetails = get_object_or_404(campaign, id=contactDetails.campaign.id)
UserDetails = get_object_or_404(User, id=1)
return render_to_response('marketing/confirm.html', {'firstEmailDetails': firstEmailDetails, 'companyDetails' : companyDetails}, context_instance=RequestContext(request))
########################################################
# This view updates the firstEmail table specified by the
# id passed in, setting MoreInformation to true.
#
########################################################
def emailMeAtLaunch(request,firstEmail_id):
firstEmailDetails = get_object_or_404(firstEmail, id=firstEmail_id)
contactDetails = get_object_or_404(contact_date, id=firstEmailDetails.contact.id)
companyDetails = get_object_or_404(company, id=contactDetails.company.id)
firstEmailDetails.MoreInformation = True
firstEmailDetails.save()
return render_to_response('marketing/thankyou.html', {'firstEmailDetails': firstEmailDetails, 'companyDetails' : companyDetails}, context_instance=RequestContext(request))
@csrf_protect
def addMeToMailingList(request):
if request.method == 'POST':
form = AddNewEmailForm(request.POST)
if form.is_valid():
form.save()
return HttpResponseRedirect(reverse('inthebackgroundSite.marketing.views.thankyou'))
else:
#print "not POST method"
form = AddNewEmailForm()
return render_to_response('marketing/addToMailingList.html', {'form': form }, context_instance=RequestContext(request))
def thankyou(request):
return render_to_response('marketing/thankyou.html')
and finally my form (sorry about all the code...)
import datetime
from django import forms
from inthebackgroundSite.marketing.models import campaign, company, contact_date, firstEmail
from django.db import transaction
from django.template import RequestContext
from django.shortcuts import render_to_response, get_list_or_404, get_object_or_404
from django.contrib.auth import authenticate
from django.contrib.auth.models import User
class AddNewEmailForm(forms.Form):
ContactPerson = forms.CharField(max_length=200)
email = forms.EmailField()
#def __init__(self, *args, **kwargs):
# self.firstEmail_id = kwargs.pop('firstEmail_id', None)
#@transaction.commit_on_success
def save(self):
now = datetime.date.today()
UserDetails = get_object_or_404(User, id=1)
campaignDetails = get_object_or_404(campaign, id=1)
#orginalFirstEmail = get_object_or_404(firstEmail, id=self.firstEmail_id)
#originalContact = get_object_or_404(contact_date, id=orginalFirstEmail.contact.id)
#originalCompany = get_object_or_404(company, id=originalContact.company.id)
newCompany = company.objects.create(company = "unknown",
address = "unknown",
street = "unknown",
suburb = "unknown",
phone_number = "unknown",
contact_person = self.cleaned_data['ContactPerson'],
email = self.cleaned_data['email'],
latitude = None,
longitude = None
)
print str(newCompany.id) + ": " + unicode(newCompany)
newContact = contact_date.objects.create(contacted = now,
who = UserDetails,
how = 'email',
company = newCompany,
campaign = campaignDetails
)
print str(newContact.id) + ": " + unicode(newContact)
newFirstEmail = firstEmail.objects.create(contact = newContact,
emailSent = False,
whoTo = "unknown",
MoreInformation = True,
comments = "This is a new addition to the mailing list that came from an unknown company.\n The company that this email was sent to is in the WhoTo",
)
print str(newFirstEmail.id) + ": " + unicode(newFirstEmail)
the problem im getting is
duplicate key value violates unique constraint "marketing_firstemail_pkey"
now normally this problem crops up if i've loaded data into postgres directly and havent updated the sequence for id. But I dont have any data in this table... none! and I still get this error.. I dont understand how that can happen.
Any help would be great!
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
我觉得还是需要调用父对象(Form)的save方法。在重写方法的开头:
I think you still need to call the save method of the parent object (Form). At the beginning of your override method:
所以我弄清楚了那是什么。
这是因为我在模型 save() 方法中进行了修改。我没有使用属性来计算 emailLink 的值,而是保存了模型两次。当发生这种情况时,我认为 Django 会缓存模型,然后尝试再次保存它。删除自定义保存表单并用此替换电子邮件链接
就可以了。感谢您的帮助!
So I worked out what it was.
It was because of a hack I did in the models save() method. Instead of using a property to calculate the value of emailLink I was saving the model twice. When this happens I think Django caches the model and then tries to save it again. removing the custom save form and replaceing the email link with this
did the trick. thanks for all your help!