django.db.utils.IntegrityError:(1062,“user_id的重复条目”)

时间:2016-06-24 14:32:21

标签: python mysql django

我有一定的模特:

class Problem(models.Model):

    title = models.CharField(max_length=80)
    problem_text = models.TextField(max_length=5000)
    pub_date = models.DateTimeField(default=timezone.now)
    votes = models.IntegerField(default=0)
    wiki_answer = models.TextField(max_length=5000, null=False, default='', blank=True)
    topic = models.CharField(max_length=50, blank=False)
    position = models.CharField(max_length=50, null=True, blank=False)
    user = models.OneToOneField(User, null=True, blank=False, unique=False)

在添加了一个用户写的多个帖子之后,即使用户不应该是唯一的,Django也会引发错误。这是完整的堆栈跟踪:

File "/Users/artemdremov/Documents/python/interview_project/venv/interview_project/lib/python3.4/site-packages/django/db/backends/utils.py" in execute
  64.                 return self.cursor.execute(sql, params)

File "/Users/artemdremov/Documents/python/interview_project/venv/interview_project/lib/python3.4/site-packages/django/db/backends/mysql/base.py" in execute
  112.             return self.cursor.execute(query, args)

File "/Users/artemdremov/Documents/python/interview_project/venv/interview_project/lib/python3.4/site-packages/mysqlclient-1.3.7-py3.4-macosx-10.6-intel.egg/MySQLdb/cursors.py" in execute
  226.             self.errorhandler(self, exc, value)

File "/Users/artemdremov/Documents/python/interview_project/venv/interview_project/lib/python3.4/site-packages/mysqlclient-1.3.7-py3.4-macosx-10.6-intel.egg/MySQLdb/connections.py" in defaulterrorhandler
  36.         raise errorvalue

File "/Users/artemdremov/Documents/python/interview_project/venv/interview_project/lib/python3.4/site-packages/mysqlclient-1.3.7-py3.4-macosx-10.6-intel.egg/MySQLdb/cursors.py" in execute
  217.             res = self._query(query)

File "/Users/artemdremov/Documents/python/interview_project/venv/interview_project/lib/python3.4/site-packages/mysqlclient-1.3.7-py3.4-macosx-10.6-intel.egg/MySQLdb/cursors.py" in _query
  378.         rowcount = self._do_query(q)

File "/Users/artemdremov/Documents/python/interview_project/venv/interview_project/lib/python3.4/site-packages/mysqlclient-1.3.7-py3.4-macosx-10.6-intel.egg/MySQLdb/cursors.py" in _do_query
  341.         db.query(q)

File "/Users/artemdremov/Documents/python/interview_project/venv/interview_project/lib/python3.4/site-packages/mysqlclient-1.3.7-py3.4-macosx-10.6-intel.egg/MySQLdb/connections.py" in query
  280.             _mysql.connection.query(self, query)

The above exception ((1062, "Duplicate entry '1' for key 'interview_questions_problem_user_id_105dd8d0_uniq'")) was the direct cause of the following exception:

File "/Users/artemdremov/Documents/python/interview_project/venv/interview_project/lib/python3.4/site-packages/django/core/handlers/base.py" in get_response
  149.                     response = self.process_exception_by_middleware(e, request)

File "/Users/artemdremov/Documents/python/interview_project/venv/interview_project/lib/python3.4/site-packages/django/core/handlers/base.py" in get_response
  147.                     response = wrapped_callback(request, *callback_args, **callback_kwargs)

File "/Users/artemdremov/Documents/python/interview_project/venv/interview_project/lib/python3.4/site-packages/django/views/generic/base.py" in view
  68.             return self.dispatch(request, *args, **kwargs)

File "/Users/artemdremov/Documents/python/interview_project/venv/interview_project/lib/python3.4/site-packages/django/views/generic/base.py" in dispatch
  88.         return handler(request, *args, **kwargs)

File "/Users/artemdremov/Documents/python/interview_project/interview_questions/views.py" in post
  55.             post.save()

File "/Users/artemdremov/Documents/python/interview_project/venv/interview_project/lib/python3.4/site-packages/django/db/models/base.py" in save
  708.                        force_update=force_update, update_fields=update_fields)

File "/Users/artemdremov/Documents/python/interview_project/venv/interview_project/lib/python3.4/site-packages/django/db/models/base.py" in save_base
  736.             updated = self._save_table(raw, cls, force_insert, force_update, using, update_fields)

File "/Users/artemdremov/Documents/python/interview_project/venv/interview_project/lib/python3.4/site-packages/django/db/models/base.py" in _save_table
  820.             result = self._do_insert(cls._base_manager, using, fields, update_pk, raw)

File "/Users/artemdremov/Documents/python/interview_project/venv/interview_project/lib/python3.4/site-packages/django/db/models/base.py" in _do_insert
  859.                                using=using, raw=raw)

File "/Users/artemdremov/Documents/python/interview_project/venv/interview_project/lib/python3.4/site-packages/django/db/models/manager.py" in manager_method
  122.                 return getattr(self.get_queryset(), name)(*args, **kwargs)

File "/Users/artemdremov/Documents/python/interview_project/venv/interview_project/lib/python3.4/site-packages/django/db/models/query.py" in _insert
  1039.         return query.get_compiler(using=using).execute_sql(return_id)

File "/Users/artemdremov/Documents/python/interview_project/venv/interview_project/lib/python3.4/site-packages/django/db/models/sql/compiler.py" in execute_sql
  1060.                 cursor.execute(sql, params)

File "/Users/artemdremov/Documents/python/interview_project/venv/interview_project/lib/python3.4/site-packages/django/db/backends/utils.py" in execute
  79.             return super(CursorDebugWrapper, self).execute(sql, params)

File "/Users/artemdremov/Documents/python/interview_project/venv/interview_project/lib/python3.4/site-packages/django/db/backends/utils.py" in execute
  64.                 return self.cursor.execute(sql, params)

File "/Users/artemdremov/Documents/python/interview_project/venv/interview_project/lib/python3.4/site-packages/django/db/utils.py" in __exit__
  95.                 six.reraise(dj_exc_type, dj_exc_value, traceback)

File "/Users/artemdremov/Documents/python/interview_project/venv/interview_project/lib/python3.4/site-packages/django/utils/six.py" in reraise
  685.             raise value.with_traceback(tb)

File "/Users/artemdremov/Documents/python/interview_project/venv/interview_project/lib/python3.4/site-packages/django/db/backends/utils.py" in execute
  64.                 return self.cursor.execute(sql, params)

File "/Users/artemdremov/Documents/python/interview_project/venv/interview_project/lib/python3.4/site-packages/django/db/backends/mysql/base.py" in execute
  112.             return self.cursor.execute(query, args)

File "/Users/artemdremov/Documents/python/interview_project/venv/interview_project/lib/python3.4/site-packages/mysqlclient-1.3.7-py3.4-macosx-10.6-intel.egg/MySQLdb/cursors.py" in execute
  226.             self.errorhandler(self, exc, value)

File "/Users/artemdremov/Documents/python/interview_project/venv/interview_project/lib/python3.4/site-packages/mysqlclient-1.3.7-py3.4-macosx-10.6-intel.egg/MySQLdb/connections.py" in defaulterrorhandler
  36.         raise errorvalue

File "/Users/artemdremov/Documents/python/interview_project/venv/interview_project/lib/python3.4/site-packages/mysqlclient-1.3.7-py3.4-macosx-10.6-intel.egg/MySQLdb/cursors.py" in execute
  217.             res = self._query(query)

File "/Users/artemdremov/Documents/python/interview_project/venv/interview_project/lib/python3.4/site-packages/mysqlclient-1.3.7-py3.4-macosx-10.6-intel.egg/MySQLdb/cursors.py" in _query
  378.         rowcount = self._do_query(q)

File "/Users/artemdremov/Documents/python/interview_project/venv/interview_project/lib/python3.4/site-packages/mysqlclient-1.3.7-py3.4-macosx-10.6-intel.egg/MySQLdb/cursors.py" in _do_query
  341.         db.query(q)

File "/Users/artemdremov/Documents/python/interview_project/venv/interview_project/lib/python3.4/site-packages/mysqlclient-1.3.7-py3.4-macosx-10.6-intel.egg/MySQLdb/connections.py" in query
  280.             _mysql.connection.query(self, query)

Exception Type: IntegrityError at /p/add/
Exception Value: (1062, "Duplicate entry '1' for key 'interview_questions_problem_user_id_105dd8d0_uniq'")

Django版本1.9.5。

以下是添加帖子表单的视图:

class AddView(View):
    template_name = 'interview_questions/add.html'
    form_class = ProblemForm
    success_url = '/'

    # display blank form
    def get(self, request):
        if request.user.is_authenticated():
            form = self.form_class(None)
            return render(request, self.template_name, {'form': form, 'user': request.user})
        else:
            return redirect('interview_questions:index')

    # process data
    def post(self, request):
        form = self.form_class(request.POST)

        if form.is_valid() and request.user.is_authenticated():
            post = form.save(commit=False)
            post.pub_date = timezone.now()
            post.user = request.user
            post.save()
            return redirect('interview_questions:index')

        return render(request, self.template_name, {'form': form, 'user': request.user})

3 个答案:

答案 0 :(得分:0)

错误发生在这里:

"/Users/artemdremov/Documents/python/interview_project/interview_questions/views.py" in post
  55.             post.save()

那是因为你的模型中有这个。

user = models.OneToOneField(User, null=True, blank=False, unique=False)

unique = False在这里没有效果,因为这里只能有一个条目。

OneToOneField

  

一对一的关系。从概念上讲,这与a类似   ForeignKey与unique = True,但关系的“反向”侧   将直接返回单个对象。

有三种解决方案

  1. 将OneToOneField更改为ForeignKey
  2. 在表单验证中,确保记录不存在
  3. 创建表单时,检查条目是否已存在,然后允许用户进行编辑。

答案 1 :(得分:0)

我正在给出一个答案,只是为了更好地理解导致此错误的原因。为什么原因是看不见的。

假设我们有一个对象,让我称之为节点

class Node(models.Model):
     next_node = models.OneToOneField("Node", blank = True, null=True)
     previous_node = models.OneToOneField("Node", blank = True, null=True)
     name = models.CharField(max_length=50, default = "Nodes Name")

然后在交互式控制台中。您可以通过python(3)manage.py shell在终端(linux,抱歉不确定Windows如何工作)中访问它。 我刚刚完成了复制此完整性错误的测试。

>>>first_node = Node()
>>> first_node.save()
>>> second_node = Node()
>>> second_node.save()
>>> third_node = Node()
>>> third_node.save()
>>> fourth_node = Node()
>>> fourth_node.save()

>>> first_node.next_node = second_node
>>> second_node.previous_node= first_node
>>> first_node.save()
>>> second_node.save()
>>> second_node.next_node = third_node
>>> third_node.previous_node=second_node
>>> second_node.save()
>>> third_node.save()
>>> second_node.next_node= fourth_node
>>> fourth_node.previous_node=second_node
>>> second_node.save()
>>> fourth_node.save()
Traceback (most recent call last):                
File
"/home/user/.local/lib/python3.5/sitepackages/django/db/
 backends/utils.py", line 64, in execute
..........
..........
..........
_mysql.connection.query(self, query)
django.db.utils.IntegrityError: 
(1062, "Duplicate entry '2' for key 'previous_node_id'")

产生此错误的原因是, 我们已经将第二个节点指定为第三个节点的前一个节点。 我们试图再次将它指定为第四个节点的previous_node。

如果您只是意识到第二个节点的正向关系,即第二个节点指向哪个并且您忘记了反向关系,那么这可能是一个问题。

考虑到模型的性质,我认为最佳解决方案是将OneToOne关系更改为ForeignKey(以便一个用户可以编写多个问题)。

如果一个用户必须遇到一个问题。然后,每当您按照e4c5的第二个解决方案中的建议保存问题时,您必须确保没有用户已经拥有该问题。

当您必须重新保存或重新分解模型时,这一点尤为重要。例如,在您使用新用户/其他用户或具有旧问题的新用户保存旧问题的情况下。例如,在后者中,您可能不会想到某个用户已经指向该问题并且您将会遇到完整性错误。

答案 2 :(得分:0)

如果要在Django中处理重复异常,请阅读此书

如何避免重复异常

我们还可以避免此类异常,首先检查Profile是否存在,然后如果不存在则创建Profile。

我们可以使用get_or_create()方法实现这一目标。


很多时候,我们需要在Model中创建唯一字段或unique_together来实现一些业务逻辑。

示例

用户和个人资料(OneToOne关系)

为每个用户创建一个配置文件。

在Django中处理重复条目异常:

如果用户已经创建了自己的个人资料再次想要创建,那么我们可以轻松地处理重复的个人资料输入。

from django.db import IntegrityError

try:
   profile = Profile.objects.create(user=someuser,imageUrl= url )
except IntegrityError:
   pass
   #Handle your exception here