django.db.utils.IntegrityError: duplicate key value violates unique constraint "spirit_category_category_pkey"
<h1>The Error</h1>

<p>I'm using django and <a href="https://github.com/nitely/Spirit" rel="noreferrer">spirit</a> to build a website. In a test, when I was inserting new data into a table called <code>spirit_category_category</code>, I got the following error:</p>

<pre><code>django.db.utils.IntegrityError: duplicate key value violates unique constraint "spirit_category_category_pkey"
DETAIL:  Key (id)=(1) already exists.
</code></pre>

<p>Note that there were already two other records in the table with ids of <code>1</code> and <code>2</code>. So inserting <code>Key(id)=(1)</code> wouldn't work, of course. But the sql executed didn't include <code>id</code> field. That is, <code>Key (id)=(1)</code> was automatically generated by postgresql, why did it generate an already existed id? </p>

<h1>The Reason</h1>

<p>To find out the reason, I ran the following command in postgresql:</p>

<pre><code>test_spiritdb=# select start_value, last_value, max_value from spirit_category_category_id_seq;
 start_value | last_value |      max_value      
-------------+------------+---------------------
           1 |          1 | 9223372036854775807
(1 row)
</code></pre>

<p>So basically, <code>last_value</code> is <code>1</code>, so postgresql will generate <code>Key (id)=(1)</code> every time, I tried to alter it to 3, and everything is fine.</p>

<pre><code>test_spiritdb=# alter sequence spirit_category_category_id_seq restart with 3;
</code></pre>

<h1>I don't know how to fix it for a test</h1>

<p>The test passed. But it is a test, so it is meaningless to alter a test table because the test database will be deleted and created again for every test, so the next time the test will fail again because <code>last_value</code> will still be generated as <code>1</code>. So I wondered why django/postgresql would generate such an abnormal value for <code>last_value</code>? How to fix it? The models and migrations for <code>category</code> are as follows, if it helps.</p>

<h1>models.py</h1>

<pre><code># -*- coding: utf-8 -*-

from __future__ import unicode_literals

from django.db import models
from django.utils.translation import ugettext_lazy as _
from django.core.urlresolvers import reverse
from django.conf import settings

from .managers import CategoryQuerySet
from ..core.utils.models import AutoSlugField

class Category(models.Model):

    parent = models.ForeignKey('self', verbose_name=_("category parent"), null=True, blank=True)

    title = models.CharField(_("title"), max_length=75)
    slug = AutoSlugField(populate_from="title", db_index=False, blank=True)
    description = models.CharField(_("description"), max_length=255, blank=True)
    is_global = models.BooleanField(_("global"), default=True,
                                    help_text=_('Designates whether the topics will be'
                                                'displayed in the all-categories list.'))
    is_closed = models.BooleanField(_("closed"), default=False)
    is_removed = models.BooleanField(_("removed"), default=False)
    is_private = models.BooleanField(_("private"), default=False)

    # topic_count = models.PositiveIntegerField(_("topic count"), default=0)

    objects = CategoryQuerySet.as_manager()

    class Meta:
        ordering = ['title', 'pk']
        verbose_name = _("category")
        verbose_name_plural = _("categories")

    def get_absolute_url(self):
        if self.pk == settings.ST_TOPIC_PRIVATE_CATEGORY_PK:
            return reverse('spirit:topic:private:index')
        else:
            return reverse('spirit:category:detail', kwargs={'pk': str(self.id), 'slug': self.slug})

    @property
    def is_subcategory(self):
        if self.parent_id:
            return True
        else:
            return False
</code></pre>

<h1>0001_initial.py</h1>

<pre><code># -*- coding: utf-8 -*-
from __future__ import unicode_literals

from django.db import models, migrations
import spirit.core.utils.models


class Migration(migrations.Migration):

    dependencies = [
    ]

    operations = [
        migrations.CreateModel(
            name='Category',
            fields=[
                ('id', models.AutoField(primary_key=True, verbose_name='ID', serialize=True, auto_created=True)),
                ('title', models.CharField(verbose_name='title', max_length=75)),
                ('slug', spirit.core.utils.models.AutoSlugField(db_index=False, populate_from='title', blank=True)),
                ('description', models.CharField(verbose_name='description', max_length=255, blank=True)),
                ('is_closed', models.BooleanField(verbose_name='closed', default=False)),
                ('is_removed', models.BooleanField(verbose_name='removed', default=False)),
                ('is_private', models.BooleanField(verbose_name='private', default=False)),
                ('parent', models.ForeignKey(null=True, verbose_name='category parent', to='spirit_category.Category', blank=True)),
            ],
            options={
                'ordering': ['title', 'pk'],
                'verbose_name': 'category',
                'verbose_name_plural': 'categories',
            },
        ),
    ]
</code></pre>

<h1>0002_auto_20150728_0442.py</h1>

<pre><code># -*- coding: utf-8 -*-
from __future__ import unicode_literals

from django.db import models, migrations
from django.conf import settings


def default_categories(apps, schema_editor):
    Category = apps.get_model("spirit_category", "Category")

    if not Category.objects.filter(pk=settings.ST_TOPIC_PRIVATE_CATEGORY_PK).exists():
        Category.objects.create(
            pk=settings.ST_TOPIC_PRIVATE_CATEGORY_PK,
            title="Private",
            slug="private",
            is_private=True
        )

    if not Category.objects.filter(pk=settings.ST_UNCATEGORIZED_CATEGORY_PK).exists():
        Category.objects.create(
            pk=settings.ST_UNCATEGORIZED_CATEGORY_PK,
            title="Uncategorized",
            slug="uncategorized"
        )


class Migration(migrations.Migration):

    dependencies = [
        ('spirit_category', '0001_initial'),
    ]

    operations = [
        migrations.RunPython(default_categories),
    ]
</code></pre>

<h1>0003_category_is_global.py</h1>

<pre><code># -*- coding: utf-8 -*-
from __future__ import unicode_literals

from django.db import models, migrations


class Migration(migrations.Migration):

    dependencies = [
        ('spirit_category', '0002_auto_20150728_0442'),
    ]

    operations = [
        migrations.AddField(
            model_name='category',
            name='is_global',
            field=models.BooleanField(default=True, help_text='Designates whether the topics will bedisplayed in the all-categories list.', verbose_name='global'),
        ),
    ]
</code></pre>