Add voting sample with ip cache
This commit is contained in:
parent
389f2bc6d1
commit
7412d5f4d9
@ -2,7 +2,7 @@
|
|||||||
<project version="4">
|
<project version="4">
|
||||||
<component name="DataSourceManagerImpl" format="xml" multifile-model="true">
|
<component name="DataSourceManagerImpl" format="xml" multifile-model="true">
|
||||||
<data-source source="LOCAL" name="clubhaus" uuid="6b646c84-5520-40ec-a76b-6001f07231ed">
|
<data-source source="LOCAL" name="clubhaus" uuid="6b646c84-5520-40ec-a76b-6001f07231ed">
|
||||||
<driver-ref>sqlite.xerial</driver-ref>
|
<driver-ref>d9daba00-9242-4b73-bac9-74aa32dd0fa2</driver-ref>
|
||||||
<synchronize>true</synchronize>
|
<synchronize>true</synchronize>
|
||||||
<jdbc-driver>org.sqlite.JDBC</jdbc-driver>
|
<jdbc-driver>org.sqlite.JDBC</jdbc-driver>
|
||||||
<jdbc-url>jdbc:sqlite:clubhaus.db</jdbc-url>
|
<jdbc-url>jdbc:sqlite:clubhaus.db</jdbc-url>
|
||||||
|
@ -96,7 +96,7 @@
|
|||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="mbr-section-btn align-center mt-5"><a class="btn btn-primary display-5"
|
<div class="row mbr-section-btn align-center mt-5"><a class="btn btn-primary display-5"
|
||||||
href="https://doodle.com/meeting/participate/id/eXDQ7OVe/vote"
|
href="https://doodle.com/meeting/participate/id/eXDQ7OVe/vote"
|
||||||
target="_blank">Terminabstimmung</a></div>
|
target="_blank">Terminabstimmung</a></div>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
@ -1,5 +1,11 @@
|
|||||||
{% load static %}
|
{% load static %}
|
||||||
|
|
||||||
|
<header>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1">
|
||||||
|
</header>
|
||||||
|
|
||||||
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css" rel="stylesheet"
|
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css" rel="stylesheet"
|
||||||
integrity="sha384-1BmE4kWBq78iYhFldvKuhfTAU6auU8tT94WrHftjDbrCEXSU1oBoqyl2QvZ6jIW3" crossorigin="anonymous">
|
integrity="sha384-1BmE4kWBq78iYhFldvKuhfTAU6auU8tT94WrHftjDbrCEXSU1oBoqyl2QvZ6jIW3" crossorigin="anonymous">
|
||||||
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/js/bootstrap.bundle.min.js"
|
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/js/bootstrap.bundle.min.js"
|
||||||
|
68
clubhaus/homepage/templates/homepage/voting.html
Normal file
68
clubhaus/homepage/templates/homepage/voting.html
Normal file
@ -0,0 +1,68 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1">
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<title>Voting</title>
|
||||||
|
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css" rel="stylesheet"
|
||||||
|
integrity="sha384-1BmE4kWBq78iYhFldvKuhfTAU6auU8tT94WrHftjDbrCEXSU1oBoqyl2QvZ6jIW3" crossorigin="anonymous">
|
||||||
|
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/js/bootstrap.bundle.min.js"
|
||||||
|
integrity="sha384-ka7Sk0Gln4gmtz2MlQnikT1wXgYsOg+OMhuP+IlRH9sENBO0LRn5q+8nbTov4+1p"
|
||||||
|
crossorigin="anonymous"></script>
|
||||||
|
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.8.3/font/bootstrap-icons.css">
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<h1>Hello Voting</h1>
|
||||||
|
|
||||||
|
{% if items %}
|
||||||
|
<h1>{{ items }}</h1>
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
{% if ip and request_count %}
|
||||||
|
<h1>Your IP is: {{ ip }} with {{ request_count }} requests</h1>
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
{% if session %}
|
||||||
|
<h1>Your session value is: {{ session.items }}</h1>
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
<!-- Button trigger modal -->
|
||||||
|
<button type="button" class="btn btn-primary" data-bs-toggle="modal" data-bs-target="#exampleModal">
|
||||||
|
Launch demo modal
|
||||||
|
</button>
|
||||||
|
|
||||||
|
<!-- Modal -->
|
||||||
|
<div class="modal fade" id="exampleModal" tabindex="-1" aria-labelledby="exampleModalLabel" aria-hidden="true">
|
||||||
|
<div class="modal-dialog">
|
||||||
|
<div class="modal-content">
|
||||||
|
<div class="modal-header">
|
||||||
|
<h5 class="modal-title" id="exampleModalLabel">Modal title</h5>
|
||||||
|
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
|
||||||
|
</div>
|
||||||
|
<form action="{% url 'voting' %}" method="post">
|
||||||
|
<div class="modal-body">
|
||||||
|
|
||||||
|
{% csrf_token %}
|
||||||
|
<label>
|
||||||
|
Key
|
||||||
|
<input type="text" name="key">
|
||||||
|
</label>
|
||||||
|
<br>
|
||||||
|
<label>
|
||||||
|
Value
|
||||||
|
<input type="text" name="value">
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
<div class="modal-footer">
|
||||||
|
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Close</button>
|
||||||
|
<button type="submit" class="btn btn-primary">Save changes</button>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</body>
|
||||||
|
</html>
|
@ -6,4 +6,5 @@ urlpatterns = [
|
|||||||
path('', views.landing, name='index'),
|
path('', views.landing, name='index'),
|
||||||
path('event', views.events, name='event'),
|
path('event', views.events, name='event'),
|
||||||
path('tobacco', views.tobacco, name='tobacco'),
|
path('tobacco', views.tobacco, name='tobacco'),
|
||||||
|
path('voting', views.voting, name='voting'),
|
||||||
]
|
]
|
@ -1,24 +1,46 @@
|
|||||||
import datetime
|
import datetime
|
||||||
|
|
||||||
import django.utils.timezone
|
import django.utils.timezone
|
||||||
|
from django.http import HttpRequest, HttpResponseRedirect
|
||||||
from django.shortcuts import render
|
from django.shortcuts import render
|
||||||
|
from django.urls import reverse
|
||||||
|
from django.core.cache import cache
|
||||||
|
|
||||||
from .models import Tobacco, TobaccoCategory, ClubhausEvent
|
from .models import Tobacco, TobaccoCategory, ClubhausEvent
|
||||||
|
|
||||||
|
|
||||||
# Create your views here.
|
def tobacco(request: HttpRequest) -> django.http.HttpResponse:
|
||||||
def tobacco(request):
|
|
||||||
test_image = Tobacco.objects.first().picture
|
test_image = Tobacco.objects.first().picture
|
||||||
context = {'tobaccos': Tobacco.objects.all(), 'categories': TobaccoCategory.objects.all(), 'pic': test_image}
|
context = {'tobaccos': Tobacco.objects.all(), 'categories': TobaccoCategory.objects.all(), 'pic': test_image}
|
||||||
return render(request, 'homepage/index.html', context)
|
return render(request, 'homepage/index.html', context)
|
||||||
|
|
||||||
|
|
||||||
def events(request):
|
def events(request: HttpRequest) -> django.http.HttpResponse:
|
||||||
yesterday = django.utils.timezone.now() - datetime.timedelta(days=1)
|
yesterday = django.utils.timezone.now() - datetime.timedelta(days=1)
|
||||||
next_events = ClubhausEvent.objects.filter(date__gte=yesterday).order_by('-date')
|
next_events = ClubhausEvent.objects.filter(date__gte=yesterday).order_by('-date')
|
||||||
next_event = next_events[0] if next_events else None
|
next_event = next_events[0] if next_events else None
|
||||||
return render(request, 'homepage/events.html', {'next_event': next_event})
|
return render(request, 'homepage/events.html', {'next_event': next_event})
|
||||||
|
|
||||||
|
|
||||||
def landing(request):
|
def landing(request: HttpRequest) -> django.http.HttpResponse:
|
||||||
return render(request, 'homepage/landingpage.html', {})
|
return render(request, 'homepage/landingpage.html', {})
|
||||||
|
|
||||||
|
|
||||||
|
def voting(request: HttpRequest) -> django.http.HttpResponse:
|
||||||
|
request.session.clear_expired()
|
||||||
|
ip = request.META.get("REMOTE_ADDR")
|
||||||
|
rate_cache: django.core.cache.BaseCache = cache
|
||||||
|
if ip not in rate_cache:
|
||||||
|
rate_cache.add(f"voting_block_{ip}", 0, 15)
|
||||||
|
rate_cache.incr(f"voting_block_{ip}")
|
||||||
|
|
||||||
|
if request.method == "GET":
|
||||||
|
return render(request, 'homepage/voting.html',
|
||||||
|
{"ip": ip, "request_count": rate_cache.get(f"voting_block_{ip}"), "session": request.session})
|
||||||
|
|
||||||
|
elif request.method == "POST":
|
||||||
|
key = request.POST["key"]
|
||||||
|
value = request.POST["value"]
|
||||||
|
request.session[key] = value
|
||||||
|
return render(request, 'homepage/voting.html', {"ip": ip, "session": request.session})
|
||||||
|
# return HttpResponseRedirect(reverse("index"))
|
||||||
|
1
clubhaus/requirements.txt
Normal file
1
clubhaus/requirements.txt
Normal file
@ -0,0 +1 @@
|
|||||||
|
django~=4.0.5
|
Loading…
Reference in New Issue
Block a user