1

For some reason on Localhost (LH) everything works fine but on my Production server, my form does not add a new user submission properly. The error I am getting is:

duplicate key value violates unique constraint "..."
DETAIL:  Key (id)=(8) already exists.

Is there some sort of production "sudo systemctl restart gunicorn" I need to run (I have already tried the example above)? Maybe it's only working on LH because there I have tested there more and the increment naturally fell on the same level as the total amount of users? I really am out of ideas here.

models.py

class Lead(models.Model):
    username = models.CharField(max_length=15, blank=True, null=True)
    email = models.CharField(unique=True, max_length=150, validators=[validate_email])
    created = models.DateTimeField(auto_now_add=True)
    ...

forms.py

class LeadCaptureForm1(forms.ModelForm):
    birth_date = forms.DateField(widget=SelectDateWidget(years=range(1999, 1910, -1)))

    class Meta:
        model = Lead
        widgets = {
            'email': forms.TextInput(attrs={'class': 'form-control'}),
        }
        fields = ('email', 'birth_date',)

views.py

def iframe1(request):
    ip = get_real_ip(request)
    created = timezone.now()

    if request.method == 'POST':

        form = LeadCaptureForm1(request.POST)
        if form.is_valid():

            # Save lead
            lead = form.save()
            # attempt at fixing it
            #lead.id = Lead.objects.get(all).count()
            #print(lead.id)
            lead.created = created
            lead.birth_date = form.cleaned_data.get('birth_date')
            lead.ipaddress = get_real_ip(request)
            lead.joinmethod = "Iframe1"
            lead.save()

            print(lead)
Alex Winkler
  • 469
  • 4
  • 25

2 Answers2

1

I'm not sure why you are setting the ID manually, and especially why you are setting it to the count of items. You should always let the database manage the primary key itself - it is an autoincrement field, and is completely opaque to your data.

The reason why you are getting this conflict is that items can be deleted, so that there can be 8 entries in the database but ID 8 already exists. But as I say, don't do this at all.

Also, don't set created manually, as that will be done automatically as well because you have auto_now_add=True in the model field.. And birth_date is set by the form save already. Finally, you should call save with commit=False if you want to set some other fields manually.

So just do:

lead = form.save(commit=False)
lead.ipaddress = get_real_ip(request)
lead.joinmethod = "Iframe1"
lead.save()
Daniel Roseman
  • 588,541
  • 66
  • 880
  • 895
  • Hey thanks for taking a look. Noticed the code above and just commented out that section because it was an attempt at fixing. So I added the "(commit=False)" and still having the same issue on production. Weird that it works on LH – Alex Winkler Apr 09 '18 at 11:05
0

This is due to the fact that we uploaded leads manually and Django uses PostgreSQL’s SERIAL data type to store auto-incrementing primary keys.

"A SERIAL column is populated with values from a sequence that keeps track of the next available value. Manually assigning a value to an auto-incrementing field doesn’t update the field’s sequence, which might later cause a conflict."

https://docs.djangoproject.com/en/2.0/ref/databases/#manually-specifying-values-of-auto-incrementing-primary-keys

To solve this we can either force a new serial number or build an exception to fix the serial. The latter option would be the ideal since we may upload users manually in the future. However, for now, we'll try and force serial number.

Run code: python manage.py sqlsequencereset [app_name]

For some reason, this did NOT work, so I was about to try and figure out how to build some sort of "python if exemption" but instead found this post first (IntegrityError duplicate key value violates unique constraint - django/postgres) that helped me directly update the "setval":

SELECT setval('tablename_id_seq', (SELECT MAX(id) FROM tablename)+1)
Alex Winkler
  • 469
  • 4
  • 25