使用get_or_create()的Django“列不唯一”

时间:2014-03-17 13:52:09

标签: database django

使用Django 1.6,我得到'django.db.utils.IntegrityError: column thread_id is not unique'。实际上,存在对象/记录#3477。但我不明白的是我正在使用get_or_create()...所以如果记录在那里它不应该尝试添加它。不知道该怎么做以及为什么这样做。

def database_udpate(thread_batch):
    sanitized_threads = [] 
    query_set = ThreadVault.objects.all()
    for thread in thread_batch:
        print thread
        obj, created = query_set.get_or_create(
                thread_id=thread["thread_id"],
                author_username=thread["author_username"],
                latest_post_date=thread["latest_post_date"],
                url=thread["url"],
                reply_count=thread["reply_count"],
                forum_id=thread["forum_id"],
                author_name=thread["author_name"],
                subject=thread["subject"],
                defaults={ 'assigned_irc_name' :
                    None }) 
        sanitized_threads.append(obj)
    unanswered_threads_table(sanitized_threads)


  File "/home/one/.virtualenvs/bot/local/lib/python2.7/site-packages/django/db/backends/sqlite3/base.py", line 450, in execute
    return Database.Cursor.execute(self, query, params)
django.db.utils.IntegrityError: column thread_id is not unique

UPDATE /修改

models.py:

class ThreadVault(models.Model):
    thread_id = models.BigIntegerField(unique=True)
    url = models.CharField(max_length="200")
    author_username = models.CharField(max_length="50")
    author_name = models.CharField(max_length="50")
    forum_id = models.CharField(max_length="50")
    subject = models.CharField(max_length="200")
    reply_count = models.CharField(max_length=("3"))
    latest_post_date = models.CharField(max_length=("50"))
    assigned_irc_name = models.ForeignKey(Employee, 
            null=True, blank=True)

    objects = models.Manager()
    #unassigned_threads = UnassignedThread()

    def __unicode__(self):
        return str(self.thread_id)

回溯:

Traceback (most recent call last):
  File "get_unaswered_threads.py", line 92, in <module>
    get_unanswered_threads()
  File "get_unaswered_threads.py", line 53, in get_unanswered_threads
    database_udpate(thread_batch)
  File "get_unaswered_threads.py", line 73, in database_udpate
    None })
  File "/home/one/.virtualenvs/bot/local/lib/python2.7/site-packages/django/db/models/query.py", line 388, in get_or_create
    six.reraise(*exc_info)
  File "/home/one/.virtualenvs/bot/local/lib/python2.7/site-packages/django/db/models/query.py", line 380, in get_or_create
    obj.save(force_insert=True, using=self.db)
  File "/home/one/.virtualenvs/bot/local/lib/python2.7/site-packages/django/db/models/base.py", line 545, in save
    force_update=force_update, update_fields=update_fields)
  File "/home/one/.virtualenvs/bot/local/lib/python2.7/site-packages/django/db/models/base.py", line 573, in save_base
    updated = self._save_table(raw, cls, force_insert, force_update, using, update_fields)
  File "/home/one/.virtualenvs/bot/local/lib/python2.7/site-packages/django/db/models/base.py", line 654, in _save_table
    result = self._do_insert(cls._base_manager, using, fields, update_pk, raw)
  File "/home/one/.virtualenvs/bot/local/lib/python2.7/site-packages/django/db/models/base.py", line 687, in _do_insert
    using=using, raw=raw)
  File "/home/one/.virtualenvs/bot/local/lib/python2.7/site-packages/django/db/models/manager.py", line 232, in _insert
    return insert_query(self.model, objs, fields, **kwargs)
  File "/home/one/.virtualenvs/bot/local/lib/python2.7/site-packages/django/db/models/query.py", line 1511, in insert_query
    return query.get_compiler(using=using).execute_sql(return_id)
  File "/home/one/.virtualenvs/bot/local/lib/python2.7/site-packages/django/db/models/sql/compiler.py", line 899, in execute_sql
    cursor.execute(sql, params)
  File "/home/one/.virtualenvs/bot/local/lib/python2.7/site-packages/django/db/backends/util.py", line 69, in execute
    return super(CursorDebugWrapper, self).execute(sql, params)
  File "/home/one/.virtualenvs/bot/local/lib/python2.7/site-packages/django/db/backends/util.py", line 53, in execute
    return self.cursor.execute(sql, params)
  File "/home/one/.virtualenvs/bot/local/lib/python2.7/site-packages/django/db/utils.py", line 99, in __exit__
    six.reraise(dj_exc_type, dj_exc_value, traceback)
  File "/home/one/.virtualenvs/bot/local/lib/python2.7/site-packages/django/db/backends/util.py", line 53, in execute
    return self.cursor.execute(sql, params)
  File "/home/one/.virtualenvs/bot/local/lib/python2.7/site-packages/django/db/backends/sqlite3/base.py", line 450, in execute
    return Database.Cursor.execute(self, query, params)
django.db.utils.IntegrityError: column thread_id is not unique

2 个答案:

答案 0 :(得分:2)

显然,自上次保存到数据库以来,其中一些字段已更改,否则您无需更新记录。 get_or_create将查询匹配所有属性,这就是为什么它不是一个非常有用的函数。您可以将不匹配的那些移动到defaults,但现在的问题是,如果记录 ,它们将不会更新。

相反,最好在try / except中使用get并在必要时进行更新:

try:
    thread_vault = ThreadVault.objects.get(id=thread['thread_id']
except ThreadVault.DoesNotExist:
    thread_vault = ThreadVault()
thread_vault.author_username=thread["author_username"]
# etc.

(似乎在即将发布的1.7版本中会有update_or_create方法完成此操作,请参阅the docs

答案 1 :(得分:1)

manual有这样说:

  

get_or_create()方法在创建()时具有类似的错误行为   您正在使用手动指定的主键。如果需要一个对象   已创建且密钥已存在于数据库中,即IntegrityError   将被提出。

我可能会离开,但是猜测:因为thread_id匹配,所有其他列也应该匹配(并且完全匹配)。由于没有发生这种情况,因此引发了IntegrityError。 也许thread_id是一个独特的列?