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。