How do I solve django.db.utils.IntegrityError: UNIQUE constraint failed? error code is django.db.utils.IntegrityError: UNIQUE constraint failed: Movies_comment.user_id, Movies_comment.tv_or_movie_id.
This error occurs Comment(comment=form.cleaned_data[“comment”],user=request.user,stars=form.cleaned_data[“stars”],tv_or_movie=tv_or_movie_object).save()
views.py
def view_tv_and_movie_detail(request, type_movie_or_tv, id): tv_or_movie_object, _ = TVAndMovie.objects.get_or_create(tmdb_id=id, judge_tv_or_movie=type_movie_or_tv) detail_tv_or_movie = TvAndMovieDetailhelp(request, tv_or_movie_object, 3) mycomment_obj = detail_tv_or_movie.get_user_post_comment_for_tv_or_movie() if request.method == "POST": if request.POST.get("action") == "delete": mycomment_obj.delete() return redirect("view_tv_and_movie_detail", type=type_movie_or_tv, id=id) else: form = CommentCreateForm(request.POST, instance=mycomment_obj) if form.is_valid() and request.POST.get("action") == "update": form.save() return redirect("view_tv_and_movie_detail", type=type_movie_or_tv, id=id) elif form.is_valid() and request.POST.get("action") == "create": Comment( comment=form.cleaned_data["comment"], user=request.user, stars=form.cleaned_data["stars"], tv_or_movie=tv_or_movie_object, ).save() return redirect("view_tv_and_movie_detail", type=type_movie_or_tv, id=id) else: form = CommentCreateForm(instance=mycomment_obj) data = detail_tv_or_movie.get_object_tv_or_movie_data() recommendations = detail_tv_or_movie.get_recommendations_tmdb_data() pages = detail_tv_or_movie.get_page_comment() average = tv_or_movie_object.average_stars() context = { "data": data, "recommendations": recommendations, "type": "movie", "mycomment": mycomment_obj, "average": average, "form": form, "pages": pages } return render(request, "Movie/movie_detail.html", context)
models.py
class TVAndMovie(models.Model): tmdb_id = models.CharField( validators=[alphanumeric], max_length=9999 ) judge_tv_or_movie = models.CharField( blank=False, null=False, default="movie", max_length=20 ) stars = models.FloatField( blank=False, null=False, default=0, validators=[MinValueValidator(0.0), MaxValueValidator(10.0)], ) def get_judge_tv_or_movie(self) -> str: return self.judge_tv_or_movie def get_comments(self) -> object: return Comment.objects.prefetch_related("tv_or_movie").filter( tv_or_movie_id=self.id ) def average_stars(self) -> float: comments = self.get_comments() n_comments = comments.count() if n_comments: self.stars = round( sum([comment.stars for comment in comments]) / n_comments, 3 ) else: self.stars = 0 self.save() return self.stars class Comment(models.Model): comment = models.TextField(max_length=1000) stars = models.FloatField( blank=False, null=False, default=0, validators=[MinValueValidator(0.0), MaxValueValidator(10.0)], ) user = models.ForeignKey(CustomUser, on_delete=models.CASCADE) tv_or_movie = models.ForeignKey(TVAndMovie, on_delete=models.CASCADE) created_at = models.DateTimeField(auto_now_add=True) updated_at = models.DateTimeField(auto_now=True) class Meta: unique_together = ("user", "tv_or_movie") indexes = [models.Index(fields=["user", "tv_or_movie"])] def __str__(self) -> str: return self.comment[:20]
helper_views.py
class TvAndMovieDetailhelp: def __init__(self, request, obj_tv_or_movie: object, page_num: int) -> None: self.request = request self.obj_tv_or_movie: object = obj_tv_or_movie self.page_num: int = page_num def get_object_tv_or_movie_data(self) -> dict: tv_or_movie_url: str = ( "https://api.themoviedb.org/3/" + self.obj_tv_or_movie.judge_tv_or_movie + "/" + str(self.obj_tv_or_movie.tmdb_id) + "?api_key=" + TMDB_API_KEY + "&language=en-US" ) return (requests.get(tv_or_movie_url)).json() def get_recommendations_tmdb_data(self) -> dict: recommendations_url: str = ( "https://api.themoviedb.org/3/" + self.obj_tv_or_movie.judge_tv_or_movie + "/" + str(self.obj_tv_or_movie.tmdb_id) + "/recommendations?api_key=" + TMDB_API_KEY + "&language=en-US" ) return (requests.get(recommendations_url)).json() def get_comment_for_tv_or_movie(self) -> object: if self.request.user.id is not None: return ( Comment.objects.filter(tv_or_movie=self.obj_tv_or_movie.id) .exclude(user=self.request.user) .order_by("-updated_at") ) else: return Comment.objects.filter(tv_or_movie=self.obj_tv_or_movie.id).order_by( "-updated_at" ) def get_user_post_comment_for_tv_or_movie(self) -> object: if self.request.user.id is not None: try: return Comment.objects.get( user=self.request.user, tv_or_movie=self.obj_tv_or_movie ) except Comment.DoesNotExist: return None else: return None def get_page_comment(self): other_comments = self.get_comment_for_tv_or_movie() paginator = Paginator(other_comments, self.page_num) page = self.request.GET.get("page", 1) try: pages = paginator.page(page) except PageNotAnInteger: pages = paginator.page(1) except EmptyPage: pages = paginator.page(1) return pages def send_contexts_detail(self,form) -> dict: data_for_tvor_movie = self.get_object_tv_or_movie_data() recommendations_data = self.get_recommendations_tmdb_data() for_movie_or_tv = self.obj_tv_or_movie.judge_tv_or_movie mycomment_obj = self.get_user_post_comment_for_tv_or_movie() average = self.obj_tv_or_movie.getaverage_stars() pages = self.get_page_comment() context = { "data": data_for_tvor_movie, "recommendations": recommendations_data, "type": for_movie_or_tv, "mycomment": mycomment_obj, "average": average, "form": form, "pages": pages, # NOTE add the comment to context } return context
Advertisement
Answer
tv_or_movie before saving i.e.
if not Comment.objects.filter(user=request.user, tv_or_movie=tv_or_movie_object).exists() Comment(comment=form.cleaned_data["comment"], user=request.user, stars=form.cleaned_data["stars"], tv_or_movie=tv_or_movie_object).save()