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
CodePudding user response:
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()