我有一定的模特:
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})
答案 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在这里没有效果,因为这里只能有一个条目。
一对一的关系。从概念上讲,这与a类似 ForeignKey与unique = True,但关系的“反向”侧 将直接返回单个对象。
有三种解决方案
答案 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