Skip to content
Advertisement

How do I solve django.db.utils.IntegrityError: UNIQUE constraint failed?

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()
Advertisement