0

I am working on a small university project. And I want to add voting to my app.

I've decided to use django-vote for it.

Here is the documentation: https://pypi.org/project/django-vote/

Upvoting works fine.

The problem is whenever I want to delete existing vote it doesn't work.

I saw this thread Django model: delete() not triggered

but I didn't understand it.

from vote.models import UP, DOWN 

...

book = get_object_or_404(Book, id=pk)

...

if 'upvote' in request.POST:
        print("I clicked upvote")
        if book.votes.exists(request.user.id):
            print("upvote exists")
            book.votes.delete(request.user.id)
        else:
            book.votes.up(request.user.id)
            
    if 'downvote' in request.POST:
        print("I clicked downvote")
        if book.votes.exists(request.user.id, action=DOWN):
            print("downvote exists")
            book.votes.delete(request.user.id)
        else:
            book.votes.down(request.user.id)

My model:

class Book(VoteModel, models.Model):
   ....
Aldiyar
  • 35
  • 5

2 Answers2

0

Either use:

book.votes.filter(user_id=request.user.id).delete()

Or:

Vote.objects.filter(user_id=request.user.id).delete()

You are not using correct Django syntax, the delete() method does not takes any params, down() is not built-in method in Django default objects manager, and exists() should be used with filter, for e.g.:

book.votes.filter(user_id=request.user.id).exists()
Patryk Szczepański
  • 731
  • 1
  • 4
  • 12
0

I couldn't figure out why delete is not working in Django-vote library in my project. I've realized that I won't be able to make it work. So I've decided to write my own custom solution for voting. Just in case if someone needs it. Here it is

votes_types=(
    ('downvote', 'downvote'),
    ('no vote', 'no vote'),
    ('upvote', 'upvote')
)

class Book(models.Model):
   ....
   num_votes_up = models.IntegerField("number of upvotes", blank=True, default=0)
   num_votes_down = models.IntegerField("number of upvotes", blank=True, default=0)

class Votes(models.Model):
    userid = models.ForeignKey(User,on_delete=models.CASCADE)
    book_id = models.ForeignKey(Book,on_delete=models.CASCADE)
    vote_type = models.TextField("Vote type", blank=True, default='no vote', choices=votes_types)

I used redirect to avoid voting twice.

def learnmore(request,pk):
    book = get_object_or_404(Book, id=pk)
    ....
    upvotes = Votes.objects.filter(userid=request.user, book_id=book, vote_type="upvote")
    downvotes = Votes.objects.filter(userid=request.user, book_id=book, vote_type="downvote")

    
    if 'upvote' in request.POST:
        upvote = Votes.objects.filter(userid=request.user, book_id=book)
        if upvote:
            upvote.delete()
            book.num_votes_up-=1
            book.save()
            messages.info(request, "upvote removed" ) 
            return redirect('/')
        else:
            upvote = Votes.objects.update_or_create(userid=request.user, book_id=book, vote_type="upvote")
            book.num_votes_up+=1
            book.save()
            messages.info(request, "upvoted" ) 
            return redirect('/')
                
    if 'downvote' in request.POST:
        downvote = Votes.objects.filter(userid=request.user, book_id=book)
        if downvote:
            downvote.delete()
            book.num_votes_down-=1
            book.save()
            messages.info(request, "downvote removed" ) 
            return redirect('/')
        else:
            downvote = Votes.objects.update_or_create(userid=request.user, book_id=book, vote_type="downvote")
            book.num_votes_down+=1
            book.save()
            messages.info(request, "downvoted" ) 
            return redirect('/')
Aldiyar
  • 35
  • 5