1

I am building an app that lets users update a webpage, but I want to restrict any user from being able to make updates every 20-30 minutes. Would I be able to simply add this logic to a view definition?

@login_required
def update_options(request):
    ...
    # logic to determine how much time passed since the user visited
    ...
    return render(request, 'main/update-options.html')
micshapicsha
  • 187
  • 3
  • 12
  • 1
    The easiest method would be to use Django's cache framework to set a userid-based cache key with a long expiry duration (such as 60 minutes). Otherwise you can add a new model field with a timestamp, or use a third party tool such as redis or memcached. – Selcuk Jan 10 '20 at 01:12

2 Answers2

2

I would do something like this. I didnt test it but it should be close.Basically use request.session to keep track of last update.

from datetime import datetime

def update_options(request):
    if request.session['last_access'] is None or (datetime.now() - request.session['last_access']).days * 24 * 60 > 30:
        'YOUR CODE HERE'
        request.session['last_access'] = datetime.now()
    else:
        'TOO MANY TRIES'
    return render(request, 'main/update-options.html')
0

I figured out a pretty simple way to do this, although the suggested answer does seem like another plausible approach. I added a field to my model which will hold a value 10 minutes from the time the user posts an update. I can then just reference that field and check if the current time is greater(later) than 10 minutes after the user's last update.

models.py

class Update(models.Model):
    update = models.IntegerField(null=True, blank=True)
    user = models.ForeignKey(User, on_delete=models.DO_NOTHING)
    date = models.DateTimeField(auto_now=True) # datetime of object creation
    next_allowed_update = models.DateTimeField(
            default=datetime.now()+timedelta(minutes=10)-timedelta(hours=5) # adjust for UTC
        )
    location = models.CharField(max_length=30, default='none')

views.py

@login_required
def update_options(request):
    # user can only update once every 10 minutes : 10 set in model
    user_latest_update = Update.objects.filter(user=request.user).latest('id')
    current_time = datetime.now().replace(tzinfo=None)   
    next_allowed_update = user_latest_update.next_allowed_update.replace(tzinfo=None)

    remaining = str(next_allowed_update - current_time).split(':')
    minutes_remaining = int(remaining[1].lstrip("0")) + 1
    if current_time > next_allowed_update:
        return render(request, 'main/update-options.html')
    else:
        return render(request, 'main/update-denied.html', {'time_remaining': minutes_remaining})

template

{% extends "main/base.html" %}

{% block content %}
<div class="container">
    <h1>You can update again in {{ time_remaining }} minute</h1>
</div>
{% endblock content %}

This solution also allows me to render a view and pass in a value to show how many minutes until the user can make another update

micshapicsha
  • 187
  • 3
  • 12