简体   繁体   中英

How do I limit requests per user in Django rest framework using throttling?

I'm working on a Quiz app and one question gets uploaded every week in a month (4 ques/month). Now I want to make sure that a logged in user can only attempt the question twice per week and not more than that. How can I do this using throttling or any other way? Here's my Quiz model:

Days = (
   ("Mon", "Monday"),
   ("Tue", "Tuesday"),
   ("Wed", "Wednesday"),
   ("Thu", "Thursday"),
   ("Fri", "Friday"),
   ("Sat", "Saturday"),
   ("Sun", "Sunday")
   )

class QuizDetail(models.Model):
    name = models.CharField(max_lenght=255, blank=False, null=False)
    start_date = models.DateTimeField()
    end_date = models.DateTimeField()
    publisehd_week_day = models.CharField(max_length=255, choices=Days)

The published_week_day can change every month, so basically one month it can be Tuesday and next month it can be Thursday.

Note: If in a month published_week_day is Tuesday and a user attempts last week's quiz on Monday and exhausts his two attempts then on Tuesday he should be able to attempt as it will be a fresh quiz.

Store it in another field

I am assuming end_date only stores the last time the quiz ended.

Create a field, say count . Now increase count by 1 everytime a test is attempted. If it reaches above 2, dont allow the quiz to be taken.

What about resetting it? You could calculate it every single time you make the request. However this is clearly extremely ineffiecient. Therefore, I would do something like so:

  1. Create another process.(Have a look at Simple approach to launching background task in Django )
  2. That process constantly searches through the database at fixed intervals.
  3. If it finds that a week has passed since the last time the user took the test, it resets the count to 0. To do this simple subtract current datetime( datetime.now() ) with end_time and compare it to 2 weeks.

You have to create one model which basically would have a relationship with your QuizDetail model

class UserQuizAttempt(models.Model)
    quiz = models.ForeignKey(QuizDetail, on_delete=models.CASCADE)
    user = models.ForeginKey(User, on_delete=models.CASCADE)
    attempt_made_on = models.DateTimeField(auto_now_add=True)

so in your views.py file, where the user will make an API call to attempt the quiz you have to check whether the user has made any attempt for that particular quiz in that particular week. If it is exceeding 2 then just return a response saying that he's exceeding the limit of the attempt for the week.

a basic example could look like this

from datetime import date

from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework import status
from rest_framework.authentication import SessionAuthentication
from rest_framework.permissions import IsAuthenticated

class QuizAPI(APIView):
    authentication_classes = [SessionAuthentication]
    permission_classes = [IsAuthenticated]
    
    def check_user_attempts(self, request, quiz_instance):
        current_week = date.today().isocalendar()[1] 
        attempts = UserQuizAttempt.objects.filter(attempt_made_on__week=current_week=current_week, quiz=quiz_instance, user=request.user)
        
       if attempts.count() > 2:
           return False

       return True

    def post(self, request):
        quiz_id = request.data.get('quiz_id')
        
        quiz_instance = QuizDetail.objects.get(id=quiz_id)

        if self.check_user_attempts(request, quiz_instance):
            UserQuizAttempt.objects.create(quiz=quiz_instance, user=request.user)
            
            # your logic goes here
            ...

        else:
            return Response("Your attempts exceeding for the week! Please try next week", status=status.HTTP_406_NOT_ACCEPTABLE)

So with this, you will have the history of the user's attempt made on the quiz which can be used for reporting or something.

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