使用每个用户的django ratelimit计算视图

时间:2014-09-30 14:42:21

标签: django

要限制前端某些模型的表单帖子,我最近开始使用django-ratelimit。我希望通过限制修改 防止滥用达到可接受的数量。

我已经让django-ratelimit在基于IP的表单上进行POST操作。但是,我想根据经过身份验证的用户对表单进行限制。似乎可以使用keys参数,但我无法理解它是如何工作的。有人在使用django-ratelimit之前做过这个吗?或者可能知道一种更好的方法来限制每个用户的表单提交?

2 个答案:

答案 0 :(得分:0)

以下方法对您有用

from django.db import models
from django.shortcuts import render_to_response
import datetime, random

class RequestRateManager(models.Manager):
    def clean_expired(self):
        """Purges old entries from database.

        If you use max_value's greater than 600 (seconds, ten minutes),
        change the following line."""
        l_time = datetime.datetime.now() - datetime.timedelta(seconds = 600)
        self.get_query_set().filter(last_update__lt=l_time).delete()

class RequestRate(models.Model):
    """Implements a rate limit per IP.

    value is increased at every request by the amount the request specifies,
    which is meant to be the average number of seconds until the same
    request could be made again.

    value decreases at a rate of 1 per second until it is a 0.
    """
    user_id = models.IntFied(blank=True, null=True)
    last_update = models.DateTimeField()
    value = models.FloatField()

    objects = RequestRateManager()

    def update(self):
        this_update = datetime.datetime.now()
        td = this_update - self.last_update
        time_delta_sec = (float(td.days) * 3600.0 * 60.0 + float(td.seconds) +
            float(td.microseconds) / 1000000.0)
        self.value -= time_delta_sec
        if self.value < 0:
            self.value = 0
        self.last_update = this_update
    def request(self, seconds, max_value):
        self.update()
        if self.value + seconds < max_value:
            self.value += seconds
            self.save()
            return True
        else:
            self.save()
            return False

def limit(seconds, max_value, per_user=True, limit_exceeded_view=None,
        limit_exceeded_template='connection_limit_exceeded.html'):
    """Makes a rate-limiting decorator"""
    def default_limit_exceeded_view(*args, **kwargs):
        return render_to_response(limit_exceeded_template)
    limit_exceeded_view = limit_exceeded_view or default_limit_exceeded_view
    def decorator(view):
        def limited_view(request, *args, **kwargs):
            if random.random() < 0.05:
                RequestRate.objects.clean_expired()
            if per_user:
                ru = request.user.id
            else:
                ru = None
            (l,tmp) = RequestRate.objects.get_or_create(user_id=ru,
                defaults={ 'last_update': datetime.datetime.now(), 'value': 0 })
            if l.request(seconds, max_value):
                return view(request, *args, **kwargs)
            else:
                return limit_exceeded_view(*args, **kwargs)
        return limited_view
    return decorator


@limit(1,1)
def your_view(request):
  pass

答案 1 :(得分:0)

如果您想根据经过身份验证的用户(即request.user)进行速率限制,则可以使用user作为密钥

从官方文档中,这里是密钥user

的用法
  

'user' - 使用来自request.user的适当值。不要与未经身份验证的用户一起使用。

以下是示例装饰器:

@ratelimit(block=True, rate='1000/m', key='user' group='ext_api')

您可以浏览密钥的所有常用选项:

https://django-ratelimit.readthedocs.io/en/latest/keys.html