Python IntegrityError:外键约束失败
我正在尝试发布表单(Python IntegrityError:外键约束失败,python,django,django-models,django-forms,Python,Django,Django Models,Django Forms,我正在尝试发布表单(ReviewForm),但当我的表单尝试保存时,出现以下错误: 外键约束失败 这是我的views.py代码(view类中的post函数) 这是我的型号.py代码: class Review(models.Model): author= models.ForeignKey(User,default=1, on_delete=models.CASCADE) time = models.DateTimeField(auto_now_add=True, blank=
ReviewForm
),但当我的表单尝试保存时,出现以下错误:
外键约束失败
这是我的views.py代码(view类中的post函数)
这是我的型号.py代码:
class Review(models.Model):
author= models.ForeignKey(User,default=1, on_delete=models.CASCADE)
time = models.DateTimeField(auto_now_add=True, blank=True)
pes = models.ForeignKey(Pestiside,default=0,on_delete=models.CASCADE)
comment = models.CharField(max_length=200)
class ReviewForm(forms.ModelForm):
class Meta:
model=Review
fields=('comment',)
这是我的表单.py代码:
class Review(models.Model):
author= models.ForeignKey(User,default=1, on_delete=models.CASCADE)
time = models.DateTimeField(auto_now_add=True, blank=True)
pes = models.ForeignKey(Pestiside,default=0,on_delete=models.CASCADE)
comment = models.CharField(max_length=200)
class ReviewForm(forms.ModelForm):
class Meta:
model=Review
fields=('comment',)
这是我的stacktrace,错误显示在views.py中的form.save()
:
Traceback (most recent call last):
File "/home/risper/django_projects/env01/lib/python3.6/site-packages/django/db/backends/utils.py", line 86, in _execute
return self.cursor.execute(sql, params)
File "/home/risper/django_projects/env01/lib/python3.6/site-packages/django/db/backends/sqlite3/base.py", line 396, in execute
return Database.Cursor.execute(self, query, params)
The above exception (FOREIGN KEY constraint failed) was the direct cause of the following exception:
File "/home/risper/django_projects/env01/lib/python3.6/site-packages/django/core/handlers/exception.py", line 34, in inner
response = get_response(request)
File "/home/risper/django_projects/env01/lib/python3.6/site-packages/django/core/handlers/base.py", line 115, in _get_response
response = self.process_exception_by_middleware(e, request)
File "/home/risper/django_projects/env01/lib/python3.6/site-packages/django/core/handlers/base.py", line 113, in _get_response
response = wrapped_callback(request, *callback_args, **callback_kwargs)
File "/home/risper/django_projects/env01/lib/python3.6/site-packages/django/views/generic/base.py", line 71, in view
return self.dispatch(request, *args, **kwargs)
File "/home/risper/django_projects/env01/lib/python3.6/site-packages/django/views/generic/base.py", line 97, in dispatch
return handler(request, *args, **kwargs)
***File "/home/risper/django_projects/Tomadoc/diagnose/views.py", line 276, in post
form.save()***
File "/home/risper/django_projects/env01/lib/python3.6/site-packages/django/forms/models.py", line 459, in save
self.instance.save()
File "/home/risper/django_projects/env01/lib/python3.6/site-packages/django/db/models/base.py", line 746, in save
force_update=force_update, update_fields=update_fields)
File "/home/risper/django_projects/env01/lib/python3.6/site-packages/django/db/models/base.py", line 784, in save_base
force_update, using, update_fields,
File "/home/risper/django_projects/env01/lib/python3.6/site-packages/django/db/models/base.py", line 887, in _save_table
results = self._do_insert(cls._base_manager, using, fields, returning_fields, raw)
File "/home/risper/django_projects/env01/lib/python3.6/site-packages/django/db/models/base.py", line 926, in _do_insert
using=using, raw=raw,
File "/home/risper/django_projects/env01/lib/python3.6/site-packages/django/db/models/manager.py", line 82, in manager_method
return getattr(self.get_queryset(), name)(*args, **kwargs)
File "/home/risper/django_projects/env01/lib/python3.6/site-packages/django/db/models/query.py", line 1204, in _insert
return query.get_compiler(using=using).execute_sql(returning_fields)
File "/home/risper/django_projects/env01/lib/python3.6/site-packages/django/db/models/sql/compiler.py", line 1391, in execute_sql
cursor.execute(sql, params)
File "/home/risper/django_projects/env01/lib/python3.6/site-packages/django/db/backends/utils.py", line 100, in execute
return super().execute(sql, params)
File "/home/risper/django_projects/env01/lib/python3.6/site-packages/django/db/backends/utils.py", line 68, in execute
return self._execute_with_wrappers(sql, params, many=False, executor=self._execute)
File "/home/risper/django_projects/env01/lib/python3.6/site-packages/django/db/backends/utils.py", line 77, in _execute_with_wrappers
return executor(sql, params, many, context)
File "/home/risper/django_projects/env01/lib/python3.6/site-packages/django/db/backends/utils.py", line 86, in _execute
return self.cursor.execute(sql, params)
File "/home/risper/django_projects/env01/lib/python3.6/site-packages/django/db/utils.py", line 90, in __exit__
raise dj_exc_value.with_traceback(traceback) from exc_value
File "/home/risper/django_projects/env01/lib/python3.6/site-packages/django/db/backends/utils.py", line 86, in _execute
return self.cursor.execute(sql, params)
File "/home/risper/django_projects/env01/lib/python3.6/site-packages/django/db/backends/sqlite3/base.py", line 396, in execute
return Database.Cursor.execute(self, query, params)
Exception Type: IntegrityError at /diagnose/pestiside/7/4
Exception Value: FOREIGN KEY constraint failed
通过保存表单,您可以保存新的审阅,因此再次手动保存它将创建第二次审阅。但是,在保存表单时会发生错误,因为您从未为疾病或用户指定
pk
对于Django,这不是问题,因为您指定了default=0
和default=1
,但并不是说存在具有该主键的用户或Pestiside
。对于大多数数据库,自动生成的主键从一个开始
您只需指定pestiside和user的值,因此:
def post(self,request, *args, **kwargs):
pk = self.kwargs['pk']
di = self.kwargs['di']
get_object_or_404(Pestiside, pk=pk, disease_id=di)
if request.method=='POST':
user = request.user
form= ReviewForm(request.POST)
if form.is_valid():
form.author = request.user
form.pes_id = pk
form.save()
return redirect('diagnose:pestiside')
不过,我不会指定默认值。在这里指定默认值没有意义,因为您需要确定视图中的作者和Pestiside
。根本不能保证具有这些主键的对象存在,而不是在开发数据库中。通过保存表单,您可以保存新的审阅,因此再次手动保存它将创建第二次审阅。但是,在保存表单时会发生错误,因为您从未为疾病或用户指定pk
对于Django,这不是问题,因为您指定了default=0
和default=1
,但并不是说存在具有该主键的用户或Pestiside
。对于大多数数据库,自动生成的主键从一个开始
您只需指定pestiside和user的值,因此:
def post(self,request, *args, **kwargs):
pk = self.kwargs['pk']
di = self.kwargs['di']
get_object_or_404(Pestiside, pk=pk, disease_id=di)
if request.method=='POST':
user = request.user
form= ReviewForm(request.POST)
if form.is_valid():
form.author = request.user
form.pes_id = pk
form.save()
return redirect('diagnose:pestiside')
不过,我不会指定默认值。在这里指定默认值没有意义,因为您需要确定视图中的作者和Pestiside
。根本不能保证具有这些主键的对象会存在,而不是在开发数据库中。提交表单后,您不需要创建审阅类的另一个实例,form.save()
会为您这样做,而且您也不会将用户分配给正在保存的实例,尝试编写如下所示的函数:
而不是:
def post(self):
...
这样做:
def form_valid(self, form): # you will need to make your view a FormView and define a form_class variable with ReviewForm
review = form.save(commit=False)
pk = self.kwargs.get("pk")
di = self.kwargs.get("di")
dis = get_object_or_404(Disease,pk=di)
pestiside = Pestiside.objects.get(pk=pk, disease=dis)
review.author = self.request.user
review.pes = pestiside
review.save()
return redirect('diagnose:pestiside')
提交表单后,您不需要创建Review类的另一个实例,form.save()
会为您创建另一个实例,而且您没有将用户分配给要保存的实例,请尝试编写如下所示的函数:
而不是:
def post(self):
...
这样做:
def form_valid(self, form): # you will need to make your view a FormView and define a form_class variable with ReviewForm
review = form.save(commit=False)
pk = self.kwargs.get("pk")
di = self.kwargs.get("di")
dis = get_object_or_404(Disease,pk=di)
pestiside = Pestiside.objects.get(pk=pk, disease=dis)
review.author = self.request.user
review.pes = pestiside
review.save()
return redirect('diagnose:pestiside')
*“如果要使用2个参数筛选它,请使用pestiside=pestiside.objects.filter(pk=pk,disease=dis.first()”-这是错误的。它执行相同的操作,只是不引发异常,但不返回任何异常。没有必要这样做“因为你有两个论点”。Get对于2-3-4-5个参数是完全有效的,只要最终结果是1个实例。@Melvyn我实际上没有意识到这一点,虽然Get只接受一个参数,谢谢,让我更正我的答案。如果找不到模型,Get()将引发DoesNotExist(如果filter()返回空queryset)。filter.first()不会引发异常。我更喜欢get(),因为如果它崩溃了,我的代码要么以一种我没有预料到的方式进化,要么我认为这必须产生一行并且只产生一行的假设是不正确的。filter.first()可能会在很久以后爆炸,使用“None type has no attribute foo”,然后您必须跟踪None的来源。有意义:)谢谢提醒*“如果要使用2个参数筛选它,请使用pestiside=pestiside.objects.filter(pk=pk,disease=dis.first()”-这是错误的。它执行相同的操作,只是不引发异常,但不返回任何异常。没有必要这样做“因为你有两个论点”。Get对于2-3-4-5个参数是完全有效的,只要最终结果是1个实例。@Melvyn我实际上没有意识到这一点,虽然Get只接受一个参数,谢谢,让我更正我的答案。如果找不到模型,Get()将引发DoesNotExist(如果filter()返回空queryset)。filter.first()不会引发异常。我更喜欢get(),因为如果它崩溃了,我的代码要么以一种我没有预料到的方式进化,要么我认为这必须产生一行并且只产生一行的假设是不正确的。filter.first()可能会在很久以后爆炸,使用“None type has no attribute foo”,然后您必须跟踪None的来源。有意义:)谢谢提醒!如果这是基于Django类的视图的post方法,则不需要检查请求方法是否为post。如果这是基于Django类的视图的post方法,则不需要检查请求方法是否为post。