Как ограничить количество запросов на пользователя в Django rest framework с помощью дросселирования?
Я работаю над приложением викторины и один вопрос загружается каждую неделю в месяц (4 вопроса в месяц). Теперь я хочу убедиться, что вошедший в систему пользователь может попытаться ответить на вопрос только два раза в неделю и не более того. Как я могу сделать это, используя дросселирование или любой другой способ? Вот моя модель викторины:
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)
День опубликованной_недели_может меняться каждый месяц, так что в основном в одном месяце это может быть вторник, а в следующем - четверг.
Примечание: Если в месяце день опубликованной_недели - вторник, а пользователь пытается пройти тест прошлой недели в понедельник и исчерпал две попытки, то во вторник он должен иметь возможность пройти тест, поскольку это будет новый тест.
Заранее спасибо.
Сохраните его в другом поле
Я предполагаю, что end_date
сохраняет только последний раз, когда викторина закончилась.
Создайте поле, скажем count
. Теперь увеличивайте count
на 1 при каждой попытке прохождения теста. Если оно достигнет значения больше 2, не позволяйте пройти тест.
А как насчет сброса? Вы могли бы вычислять его каждый раз, когда вы делаете запрос. Однако это явно крайне неэффективно. Поэтому я бы сделал примерно так:
- Создайте другой процесс. (Посмотрите Простой подход к запуску фонового задания в Django) .
- Этот процесс постоянно выполняет поиск в базе данных через фиксированные интервалы времени.
- Если он обнаруживает, что с момента последнего прохождения теста прошла неделя, он сбрасывает счетчик на 0. Для этого просто вычтите текущее время (
datetime.now()
) изend_time
и сравните его с 2 неделями.
Вы должны создать одну модель, которая в основном будет иметь отношения с вашей QuizDetail
моделью
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)
Итак, в файле views.py, где пользователь будет делать вызов API, чтобы попытаться пройти тест, вы должны проверить, сделал ли пользователь хоть одну попытку для этого конкретного теста на этой конкретной неделе. Если оно превышает 2, то просто верните ответ, говорящий, что он превысил лимит попыток на неделю.
Основной пример может выглядеть следующим образом
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)
Таким образом, у вас будет история попыток пользователя в тесте, которая может быть использована для отчетности или чего-то еще.