简体   繁体   中英

Django I want to limit user voting to once per 24 hours but I limited it per article and not per user

I would like to kindly ask you for your help. I wanted to create simply voting system for questions. And I succeded, then I wanted to limit users to voting only once per 24 hours and I failed miserable.

I know what I want to achieve but I don't know how to code it.

Right now with my mistake I limited voting on QUESTION once per 24 hours. Instead of that I wanted to limit one USER to vote ONCE per 24 hour on EACH question. So I made pretty stupid mistake. Here is my code with my mistake:

models.py:

class Question(models.Model):
    question = models.CharField(max_length=300)
    answered = models.BooleanField(default=False)
    created = models.DateTimeField(auto_now_add=True)
    datecompleted = models.DateTimeField(null=True, blank=True)
    user = models.ForeignKey(User, on_delete=models.CASCADE)
    votesscore = models.IntegerField(default='0')
    votescoresubmitted = models.DateTimeField(null=True, blank=True)
    amountofvotes = models.IntegerField(default='0')

    def __str__(self):
        return self.question

views.py:

@login_required()
def questionvoteup(request, question_pk):
    question = get_object_or_404(Question, pk=question_pk, user=request.user)
    if request.is_ajax() and request.method == "POST":
        if question.votescoresubmitted is None or timezone.now() > question.votescoresubmitted + timedelta(minutes=1440):
            question.votesscore += 1
            question.amountofvotes += 1
            question.votescoresubmitted = timezone.now()
            question.save()
            data = {
                "msg": 'Thank you for your vote!'
            }
            return JsonResponse(data)
        else:
            raise forms.ValidationError("You can vote only one time every 24 hours.")
    else:
        return HttpResponse(400, 'Invalid form')

Right now I can see it clearly. I think that I need to add this "votescoresubmitted" to User class, and make it somehow unique for each question. But I cannot think of idea how I should approach this. I will be very grateful for your help.

Thank you.


Edit:

I fought with it and I came up with additional model that should store informations about votes. Right now my code looks like this: models.py:

from django.db import models
from django.contrib.auth.models import User


class Question(models.Model):
    question = models.CharField(max_length=300)
    answered = models.BooleanField(default=False)
    created = models.DateTimeField(auto_now_add=True)
    datecompleted = models.DateTimeField(null=True, blank=True)
    user = models.ForeignKey(User, on_delete=models.CASCADE)

    def __str__(self):
        return self.question


class Answer(models.Model):
    question_id = models.ForeignKey(Question, on_delete=models.CASCADE, blank=False, null=True)
    answer = models.TextField(max_length=1000)
    created = models.DateTimeField(auto_now_add=True)
    user = models.ForeignKey(User, on_delete=models.CASCADE)

    def __str__(self):
        return self.answer


class VoteQuestion(models.Model):
    user = models.ForeignKey(User, on_delete=models.CASCADE)
    question_id = models.ForeignKey(Question, on_delete=models.CASCADE, blank=False, null=True)
    votesubmitted = models.DateTimeField(null=True, blank=True)
    votesscore = models.IntegerField(default='0')
    amountofvotes = models.IntegerField(default='0')

views.py:

@login_required()
def questionvoteup(request, question_pk):
    votequestion = get_object_or_404(VoteQuestion, pk=question_pk, user=request.user)
    current_time = timezone.now()
    if request.is_ajax() and request.method == "POST":
        if not votequestion.votesubmitted or current_time > votequestion.votesubmitted + timedelta(days=1):
            votequestion.votesscore += 1
            votequestion.amountofvotes += 1
            votequestion.votesubmitted = current_time
            votequestion.save()
            msg = "Thank you for your vote!"
        else:
            msg = "You can vote only one time every 24 hours."
        data = {"msg": msg}
        return JsonResponse(data)
    else:
        return HttpResponse(400, 'Invalid form')

and home.html (where I trigger vote UP):

<ul>
    {% for question in allquestionswithanswers %}
    <li>
        {{ question }} Score: {{ VoteQuestion.votesscore }} {{ question.user }}
        <br><br>

        <form class='my-ajax-form' method='POST' action='' data-url="{% url 'questionvoteup' question.id %}" >
        {% csrf_token %}
        <button type='submit'>UP</button>
        </form>



        {% for answer in question.answer_set.all %}
            {{ answer }}<br>
        {% endfor %}
    </li>
    {% endfor %}

</ul>

Yet, after I click "UP" I get error:

Page not found at /viewquestion/6/voteup
No VoteQuestion matches the given query.

There are several ways to do that:

  • Record votes as independent objects that are tied to a user and question
  • Record a user's voting history as part of that user's object

The first one, you would do is create a vote object with related fields user and question (many-to-one relationship ForeignKey ). This way is almost always easier to do.

Second way, add a custom field to User model to track voting history for that user. See extending Django's default User



And, perhaps, in your view instead of ValidationError give also a message:

@login_required
def questionvoteup(request, question_pk):
    if request.is_ajax() and request.method == "POST":
        current_time = timezone.now()
        votequestion, created = VoteQuestion.objects.get_or_create(question_id=question_pk, user=request.user)
        if not votequestion.votescoresubmitted or current_time > votequestion.votescoresubmitted + timedelta(days=1):
            votequestion.votesscore += 1
            votequestion.amountofvotes += 1
            votequestion.votescoresubmitted = current_time
            votequestion.save()
            msg = "Thank you for your vote!"
        else:
            msg = "You can vote only one time every 24 hours."
        data = {
            "msg": msg
        }
        return JsonResponse(data)
    else:
        return HttpResponse(400, 'Invalid form')

And your VoteQuestion model:

class VoteQuestion(models.Model):
    user = models.ForeignKey(User, on_delete=models.CASCADE)
    question = models.ForeignKey(Question, on_delete=models.CASCADE)
    votesubmitted = models.DateTimeField(null=True, blank=True)
    votesscore = models.IntegerField(default=0)
    amountofvotes = models.IntegerField(default=0)

    class Meta:
        unique_together = ['user', 'question']

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM