如何解决Django影评提交与更新功能中的IntegrityError问题
Hey there, let's figure out why your review form is throwing those errors and fix it up.
First, let's unpack the error messages:
- The first
reviews.DoesNotExistmakes sense—it just means the user hasn't submitted a review for this movie yet, so yourget()call can't find an existing record. - The real problem comes in the
exceptblock: when you create a newreviewsinstance, you're not setting themovieanduserfields. Since these are required ForeignKeys in your model, the database rejects the save becausemovie_id(anduser_id) can't be null.
Here's how to fix this, step by step:
1. Fix the new review creation in the except block
You need to associate the new review with both the current movie and the logged-in user. Update your views.py code like this:
First, make sure you import the necessary modules (if you haven't already):
from django.core.exceptions import ObjectDoesNotExist from .models import reviews, details # Ensure details is your Movie model from django.contrib.auth.decorators import login_required
Then modify the user_reviews view:
@login_required # Add this to ensure only logged-in users can submit reviews def user_reviews(request, movies_id): url = request.META.get('HTTP_REFERER') if request.method == 'POST': try: # Try to get existing review for this user and movie ureview = reviews.objects.get(movie__id=movies_id, user__id=request.user.id) form = ReviewForm(request.POST, instance=ureview) form.save() return redirect(url) except ObjectDoesNotExist: form = ReviewForm(request.POST) if form.is_valid(): data = reviews() # Set the required ForeignKey fields (this fixes the null error) data.movie = details.objects.get(id=movies_id) # Link to the correct movie data.user = request.user # Link to the logged-in user # Set the other fields from the form data.title = form.cleaned_data['title'] data.review = form.cleaned_data['review'] data.rating = form.cleaned_data['rating'] data.ip = request.META.get('REMOTE_ADDR') data.save() return redirect(url) # Add handling for GET requests (when user first loads the page) else: # Optionally pre-fill form if user has an existing review try: existing_review = reviews.objects.get(movie__id=movies_id, user__id=request.user.id) form = ReviewForm(instance=existing_review) except ObjectDoesNotExist: form = ReviewForm() return render(request, 'your_review_template.html', {'form': form, 'movies_id': movies_id})
2. Why this works:
@login_requiredensuresrequest.useris always a valid logged-in user, preventing issues with anonymous users trying to submit reviews.- We explicitly set
data.movieto thedetailsobject matchingmovies_id, anddata.usertorequest.user. This populates the requiredmovie_idanduser_idfields in the database, fixing theIntegrityError. - Added handling for GET requests—your original code didn't account for this, which could lead to unexpected behavior when users first navigate to the review page.
Bonus: Use ModelForm for cleaner code
Your ReviewForm should probably be a ModelForm, which simplifies creating/updating instances without manually assigning fields. Here's how that would look:
In forms.py:
from django import forms from .models import reviews class ReviewForm(forms.ModelForm): class Meta: model = reviews fields = ['title', 'review', 'rating'] # Fields users can edit
Then your view can be simplified even more:
@login_required def user_reviews(request, movies_id): url = request.META.get('HTTP_REFERER') movie = details.objects.get(id=movies_id) # Get the movie once try: existing_review = reviews.objects.get(movie=movie, user=request.user) except ObjectDoesNotExist: existing_review = None if request.method == 'POST': form = ReviewForm(request.POST, instance=existing_review) if form.is_valid(): review = form.save(commit=False) review.movie = movie review.user = request.user review.ip = request.META.get('REMOTE_ADDR') review.save() return redirect(url) else: form = ReviewForm(instance=existing_review) return render(request, 'your_review_template.html', {'form': form, 'movie': movie})
This version is cleaner, less error-prone, and follows Django best practices.
Final Checks:
- Confirm your
detailsmodel is correctly imported in views.py. - Ensure your template is passing the correct
movies.idto the form's action URL (your existing HTML looks okay for this). - Test both submitting a new review and updating an existing one to confirm the fix works.
内容的提问来源于stack exchange,提问作者Abin Benny

