1
\$\begingroup\$

I have a function with multiple if else statements that I'm trying to simplify in Django

Is there a pattern or maybe a better modeling approach that I could use here?

The idea behind is to have a thumbs up, thumbs down behavior for each blog post

views.py

@login_required
def blog_post_vote(request, slug):
 post = get_object_or_404(BlogPost, slug=slug)
 if request.method == "POST":
 vote = request.POST['vote']
 has_user_voted = BlogPostUserVote.objects.filter(blog_post=post, user=request.user).count()
 if has_user_voted == 0:
 if vote == "yes":
 user_vote_yes = BlogPostUserVote(blog_post=post, user=request.user, vote_yes=1)
 user_vote_yes.save()
 if vote == "no":
 user_vote_no = BlogPostUserVote(blog_post=post, user=request.user, vote_no=1)
 user_vote_no.save()
 else:
 has_user_voted_yes = BlogPostUserVote.objects.filter(blog_post=post, user=request.user, vote_yes=1).count()
 has_user_voted_no = BlogPostUserVote.objects.filter(blog_post=post, user=request.user, vote_no=1).count()
 if vote == "yes" and has_user_voted_yes == 0:
 user_vote_yes = BlogPostUserVote(blog_post=post, user=request.user, vote_yes=1)
 user_vote_yes.save()
 BlogPostUserVote.objects.filter(blog_post=post, user=request.user, vote_no=1).delete()
 if vote == "no" and has_user_voted_no == 0:
 user_vote_no = BlogPostUserVote(blog_post=post, user=request.user, vote_no=1)
 user_vote_no.save()
 BlogPostUserVote.objects.filter(blog_post=post, user=request.user, vote_yes=1).delete()
 return redirect(request.META['HTTP_REFERER'])

models.py

class BlogPost(models.Model):
 user = models.ForeignKey(User, on_delete=models.CASCADE)
 image = models.ImageField(upload_to='images/', blank=True, null=True)
 title = models.CharField(max_length=500)
 # Slug = Short URL Label
 slug = models.SlugField(unique=True)
 content = models.TextField(null=True, blank=True)
 publish_date = models.DateTimeField(
 auto_now=False, auto_now_add=False, null=True, blank=True)
 timestamp = models.DateTimeField(auto_now=True)
 updated = models.DateTimeField(auto_now=True)
 @property
 def thumbs_up(self):
 return BlogPostUserVote.objects.filter(blog_post=self).aggregate(Sum("vote_yes"))['vote_yes__sum']
 @property
 def thumbs_down(self):
 return BlogPostUserVote.objects.filter(blog_post=self).aggregate(Sum("vote_no"))['vote_no__sum']
 # This line is very important as it maps the objects to the default manager
 objects = BlogPostManager()
 # Ordering Newest to Oldest
 class Meta:
 ordering = ['-publish_date', '-updated', '-timestamp']
 def get_absolute_url(self):
 return f"/blog/{self.slug}"
class BlogPostUserVote(models.Model):
 blog_post = models.ForeignKey(BlogPost, on_delete=models.CASCADE)
 user = models.ForeignKey(User, on_delete=models.CASCADE)
 vote_yes = models.SmallIntegerField(null=True, blank=True)
 vote_no = models.SmallIntegerField(null=True, blank=True)
asked Dec 26, 2020 at 20:48
\$\endgroup\$
3
  • \$\begingroup\$ What are has_user_voted and friends? Reading the variable name, I would think a boolean True/False. But you keep checking if ==0 instead. \$\endgroup\$ Commented Dec 26, 2020 at 22:03
  • \$\begingroup\$ Hi, it is a query against the BlogPostUserVote table and if it finds any record with the given filter will return a number greather than 0. Not exactly a boolean though \$\endgroup\$ Commented Dec 26, 2020 at 22:23
  • 1
    \$\begingroup\$ Your title is too generic. Please read codereview.stackexchange.com/help/how-to-ask . \$\endgroup\$ Commented Dec 27, 2020 at 8:41

1 Answer 1

1
\$\begingroup\$

Well finally I ended up with the following, I changed some names to make it more explanatory and the function to respond to an ajax request. However the logic is pretty much the same:

@login_required
@csrf_exempt
def blog_post_reaction(request, slug):
 post = get_object_or_404(BlogPost, slug=slug)
 if request.is_ajax and request.method == "POST":
 reaction = json.loads(request.body)['vote']
 BlogPostUserReaction.objects.filter(blog_post=post, user=request.user).delete()
 new_user_reaction = BlogPostUserReaction(blog_post=post, user=request.user)
 if reaction == "upvote":
 new_user_reaction.upvote = 1
 if reaction == "downvote":
 new_user_reaction.downvote = 1
 if any((new_user_reaction.upvote, new_user_reaction.downvote)):
 new_user_reaction.save()
 return JsonResponse({'slug': slug, 'upvotes': post.upvote, 'downvotes': post.downvote})
answered Dec 27, 2020 at 19:36
\$\endgroup\$

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.