简体   繁体   中英

IntegrityError: FOREIGN KEY constraint failed

I am trying to post a form ( ReviewForm ) but I get the following error when my form tries to save:

FOREIGN KEY constraint failed

Here is my views.py code (the post function in the view class)

def post(self,request,*args,**kwargs):
    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)
           
    if request.method=='POST':
        user = request.user
        form= ReviewForm(request.POST)
        if form.is_valid():
            
            form.save()
            comment=form.cleaned_data.get('comment')
            new_review=Review.objects.create(author=user,pes_id=pestiside_id,comment=comment)
            new_review.save()  
        return redirect('diagnose:pestiside')       

Here is my models.py code:

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)

Here is my forms.py code:

class ReviewForm(forms.ModelForm):
    class Meta:
        model=Review
        fields=('comment',)

Here is my stacktrace, the error shows at form.save() in views.py:

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

By saving the form, you save the new review, so manually saving it a second time will create a second review. The error however occurs when you save the form, since you never specified the pk for the disease or the user.

For Django, that is not a problem, since you specified default=0 and default=1 , but it is not said that a User or Pestiside with that primary key exists. For most databases automatically generated primary keys start with one .

You should simply specify the values for the pestiside and user, so:

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
            form
            form.save()
        return redirect('diagnose:pestiside')

As @Melvyn says , the class-based view will only call post in case it is a POST request, so there is no need to check this. You furthermore might want to use a class-based view like a CreateView [Django-doc] which can elminate a lot of boilerplate code:

from django.urls import reverse_lazy
from django.views.generic.edit import CreateView

class CreateReviewView(CreateView):
    model = Review
    form_class = ReviewForm
    sucess_url = reverse_lazy('diagnose:pestiside')
    
    def form_valid(self, form):
        form
        form
        return super().form_valid(form)

I would however simply not specify default values. It makes no sense to specify a default here, since you will need to determine the author and the Pestiside in the view. It is not guaranteed at all that objects with these primary keys will exist, not on the development database.

You dont need to create another instance of your Review class after submitting the form, form.save() does that for you, also you are not assigning your user to the instance that is being saved, try to write your function like shown below:

Instead of:

def post(self):
    ...

do this:

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')

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM