mirror of
https://github.com/Sosokker/ku-polls.git
synced 2025-12-19 05:24:05 +01:00
Add up/down Vote + Update admin field
This commit is contained in:
parent
c3b5984e33
commit
f6d0239ec6
133
data/polls.json
133
data/polls.json
@ -8,9 +8,6 @@
|
||||
"end_date": "2023-09-29T20:31:49Z",
|
||||
"short_description": "Cool kids have polls",
|
||||
"long_description": "No description provide for this poll.",
|
||||
"up_vote_count": 5,
|
||||
"down_vote_count": 0,
|
||||
"participant_count": 6,
|
||||
"tags": []
|
||||
}
|
||||
},
|
||||
@ -23,9 +20,6 @@
|
||||
"end_date": "2023-10-18T23:50:19Z",
|
||||
"short_description": "Cool kids have polls",
|
||||
"long_description": "No description provide for this poll.",
|
||||
"up_vote_count": 1,
|
||||
"down_vote_count": 0,
|
||||
"participant_count": 0,
|
||||
"tags": []
|
||||
}
|
||||
},
|
||||
@ -38,9 +32,6 @@
|
||||
"end_date": "2023-11-28T19:50:53Z",
|
||||
"short_description": "Cool kids have polls",
|
||||
"long_description": "No description provide for this poll.",
|
||||
"up_vote_count": 1,
|
||||
"down_vote_count": 0,
|
||||
"participant_count": 0,
|
||||
"tags": []
|
||||
}
|
||||
},
|
||||
@ -53,9 +44,6 @@
|
||||
"end_date": "2023-09-29T17:51:18Z",
|
||||
"short_description": "Cool kids have polls",
|
||||
"long_description": "No description provide for this poll.",
|
||||
"up_vote_count": 10,
|
||||
"down_vote_count": 0,
|
||||
"participant_count": 0,
|
||||
"tags": []
|
||||
}
|
||||
},
|
||||
@ -144,7 +132,7 @@
|
||||
"model": "polls.vote",
|
||||
"pk": 2,
|
||||
"fields": {
|
||||
"choice": 2,
|
||||
"choice": 1,
|
||||
"user": 3,
|
||||
"question": 1
|
||||
}
|
||||
@ -153,7 +141,7 @@
|
||||
"model": "polls.vote",
|
||||
"pk": 3,
|
||||
"fields": {
|
||||
"choice": 1,
|
||||
"choice": 2,
|
||||
"user": 2,
|
||||
"question": 1
|
||||
}
|
||||
@ -248,6 +236,24 @@
|
||||
"question": 3
|
||||
}
|
||||
},
|
||||
{
|
||||
"model": "polls.vote",
|
||||
"pk": 14,
|
||||
"fields": {
|
||||
"choice": 7,
|
||||
"user": 3,
|
||||
"question": 4
|
||||
}
|
||||
},
|
||||
{
|
||||
"model": "polls.vote",
|
||||
"pk": 15,
|
||||
"fields": {
|
||||
"choice": 2,
|
||||
"user": 6,
|
||||
"question": 1
|
||||
}
|
||||
},
|
||||
{
|
||||
"model": "polls.sentimentvote",
|
||||
"pk": 1,
|
||||
@ -256,5 +262,104 @@
|
||||
"question": 1,
|
||||
"vote_types": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"model": "polls.sentimentvote",
|
||||
"pk": 2,
|
||||
"fields": {
|
||||
"user": 2,
|
||||
"question": 2,
|
||||
"vote_types": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"model": "polls.sentimentvote",
|
||||
"pk": 3,
|
||||
"fields": {
|
||||
"user": 2,
|
||||
"question": 4,
|
||||
"vote_types": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"model": "polls.sentimentvote",
|
||||
"pk": 4,
|
||||
"fields": {
|
||||
"user": 2,
|
||||
"question": 3,
|
||||
"vote_types": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"model": "polls.sentimentvote",
|
||||
"pk": 5,
|
||||
"fields": {
|
||||
"user": 2,
|
||||
"question": 1,
|
||||
"vote_types": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"model": "polls.sentimentvote",
|
||||
"pk": 6,
|
||||
"fields": {
|
||||
"user": 6,
|
||||
"question": 1,
|
||||
"vote_types": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"model": "polls.sentimentvote",
|
||||
"pk": 7,
|
||||
"fields": {
|
||||
"user": 6,
|
||||
"question": 3,
|
||||
"vote_types": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"model": "polls.sentimentvote",
|
||||
"pk": 8,
|
||||
"fields": {
|
||||
"user": 6,
|
||||
"question": 4,
|
||||
"vote_types": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"model": "polls.sentimentvote",
|
||||
"pk": 9,
|
||||
"fields": {
|
||||
"user": 3,
|
||||
"question": 1,
|
||||
"vote_types": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"model": "polls.sentimentvote",
|
||||
"pk": 10,
|
||||
"fields": {
|
||||
"user": 3,
|
||||
"question": 3,
|
||||
"vote_types": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"model": "polls.sentimentvote",
|
||||
"pk": 11,
|
||||
"fields": {
|
||||
"user": 3,
|
||||
"question": 4,
|
||||
"vote_types": false
|
||||
}
|
||||
},
|
||||
{
|
||||
"model": "polls.sentimentvote",
|
||||
"pk": 12,
|
||||
"fields": {
|
||||
"user": 3,
|
||||
"question": 2,
|
||||
"vote_types": true
|
||||
}
|
||||
}
|
||||
]
|
||||
|
||||
@ -13,11 +13,10 @@ class QuestionAdmin(admin.ModelAdmin):
|
||||
(None, {"fields": ["question_text"]}),
|
||||
("Published date", {"fields": ["pub_date"], "classes": ["collapse"]}),
|
||||
("End date", {"fields": ["end_date"], "classes": ["collapse"]}),
|
||||
("Sentiment Vote count", {"fields": ["up_vote_count", "down_vote_count"]}),
|
||||
]
|
||||
list_display = ["question_text", "pub_date", "end_date", "was_published_recently", "can_vote"]
|
||||
inlines = [ChoiceInline]
|
||||
list_filter = ["pub_date", ]
|
||||
list_filter = ["pub_date", "end_date"]
|
||||
search_fields = ["question_text"]
|
||||
|
||||
|
||||
|
||||
@ -0,0 +1,25 @@
|
||||
# Generated by Django 4.2.4 on 2023-09-14 19:15
|
||||
|
||||
from django.db import migrations
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('polls', '0013_alter_vote_question'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.RemoveField(
|
||||
model_name='question',
|
||||
name='down_vote_count',
|
||||
),
|
||||
migrations.RemoveField(
|
||||
model_name='question',
|
||||
name='participant_count',
|
||||
),
|
||||
migrations.RemoveField(
|
||||
model_name='question',
|
||||
name='up_vote_count',
|
||||
),
|
||||
]
|
||||
@ -12,7 +12,6 @@ Attributes:
|
||||
from django.db import models, IntegrityError
|
||||
from django.utils import timezone
|
||||
from django.contrib import admin
|
||||
from django.core.validators import MaxValueValidator, MinValueValidator
|
||||
from django.db.models import Sum
|
||||
from django.contrib.auth.models import User
|
||||
|
||||
@ -49,10 +48,6 @@ class Question(models.Model):
|
||||
long_description = models.TextField(max_length=2000, default="No description provide for this poll.")
|
||||
tags = models.ManyToManyField(Tag, blank=True)
|
||||
|
||||
up_vote_count = models.PositiveIntegerField(default=0, validators=[MinValueValidator(0), MaxValueValidator(2147483647)])
|
||||
down_vote_count = models.PositiveIntegerField(default=0, validators=[MinValueValidator(0), MaxValueValidator(2147483647)])
|
||||
participant_count = models.PositiveIntegerField(default=0, validators=[MinValueValidator(0), MaxValueValidator(2147483647)])
|
||||
|
||||
def was_published_recently(self):
|
||||
"""
|
||||
Checks if the question was published recently or not.
|
||||
@ -164,7 +159,6 @@ class Question(models.Model):
|
||||
def upvote(self, user):
|
||||
try:
|
||||
self.sentimentvote_set.create(user=user, question=self, vote_types=True)
|
||||
self.up_vote_count += 1
|
||||
self.save()
|
||||
except IntegrityError:
|
||||
vote = self.sentimentvote_set.filter(user=user)
|
||||
@ -175,11 +169,9 @@ class Question(models.Model):
|
||||
return False
|
||||
return True
|
||||
|
||||
|
||||
def downvote(self, user):
|
||||
try:
|
||||
self.sentimentvote_set.create(user=user, question=self, vote_types=False)
|
||||
self.up_vote_count += 1
|
||||
self.save()
|
||||
except IntegrityError:
|
||||
vote = self.sentimentvote_set.filter(user=user)
|
||||
@ -190,6 +182,14 @@ class Question(models.Model):
|
||||
return False
|
||||
return True
|
||||
|
||||
@property
|
||||
def up_vote_count(self):
|
||||
return self.sentimentvote_set.filter(question=self, vote_types=True).count()
|
||||
|
||||
@property
|
||||
def down_vote_count(self):
|
||||
return self.sentimentvote_set.filter(question=self, vote_types=False).count()
|
||||
|
||||
|
||||
class Choice(models.Model):
|
||||
"""
|
||||
|
||||
@ -11,6 +11,16 @@
|
||||
<div class="flex flex-wrap items-center space-x-2">
|
||||
<header class="flex items-center justify-center">
|
||||
<div class="flex flex-wrap items-center space-x-2">
|
||||
<form method="post" action="{% url "polls:upvote" question.id %}">
|
||||
{% csrf_token %}
|
||||
<button class="flex items-center whitespace-nowrap rounded-full border-black border-2 border-solid bg-neutral-200 px-5 py-2 text-sm font-bold text-black transition duration-150 ease-in-out hover:scale-[101%] hover:bg-green-500 focus:bg-orange-700 focus:outline-none focus:ring-2 focus:ring-red-500 focus:ring-offset-2 active:bg-orange-900"
|
||||
type="submit" {% if user_voted == 'upvote' %}disabled{% endif %}>Upvote👍</button>
|
||||
</form>
|
||||
<form method="post" action="{% url "polls:downvote" question.id %}">
|
||||
{% csrf_token %}
|
||||
<button class="flex items-center whitespace-nowrap rounded-full border-black border-2 border-solid bg-neutral-200 px-5 py-2 text-sm font-bold text-black transition duration-150 ease-in-out hover:scale-[101%] hover:bg-yellow-500 focus:bg-orange-700 focus:outline-none focus:ring-2 focus:ring-red-500 focus:ring-offset-2 active:bg-orange-900"
|
||||
type="submit" {% if user_voted == 'downvote' %}disabled{% endif %}>Downvote👎</button>
|
||||
</form>
|
||||
<!--End-->
|
||||
<button
|
||||
onclick="window.location.href='{% url 'polls:index' %}'"
|
||||
|
||||
@ -9,4 +9,6 @@ urlpatterns = [
|
||||
path("<int:pk>/results/", views.ResultsView.as_view(), name="results"),
|
||||
path("<int:question_id>/vote/", views.vote, name="vote"),
|
||||
path("signup/", views.SignUpView.as_view(), name="signup"),
|
||||
path("upvote/<int:question_id>", views.up_down_vote, {'vote_type' : 'upvote'}, name="upvote"),
|
||||
path("downvote/<int:question_id>", views.up_down_vote, {'vote_type' : 'downvote'}, name="downvote"),
|
||||
]
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
import logging
|
||||
from typing import Any
|
||||
|
||||
from django.shortcuts import get_object_or_404, render, redirect
|
||||
from django.urls import reverse
|
||||
@ -86,9 +87,18 @@ class ResultsView(LoginRequiredMixin, generic.DetailView):
|
||||
model = Question
|
||||
template_name = "polls/results.html"
|
||||
|
||||
def render_to_response(self, context, **response_kwargs):
|
||||
return render(self.request, self.template_name, context)
|
||||
def get_context_data(self, **kwargs: Any) -> dict[str, Any]:
|
||||
context = super().get_context_data(**kwargs)
|
||||
|
||||
user_voted = None
|
||||
question = self.get_object()
|
||||
if question.sentimentvote_set.filter(user=self.request.user, question=question, vote_types=True).exists():
|
||||
user_voted = 'upvote'
|
||||
elif question.sentimentvote_set.filter(user=self.request.user, question=question, vote_types=False).exists():
|
||||
user_voted = 'downvote'
|
||||
|
||||
context['user_voted'] = user_voted
|
||||
return context
|
||||
|
||||
class SignUpView(generic.CreateView):
|
||||
form_class = SignUpForm
|
||||
@ -139,6 +149,22 @@ def vote(request, question_id):
|
||||
return redirect("polls:index")
|
||||
|
||||
|
||||
@login_required
|
||||
def up_down_vote(request, question_id, vote_type):
|
||||
ip = get_client_ip(request)
|
||||
question = get_object_or_404(Question, pk=question_id)
|
||||
|
||||
if request.method == "POST":
|
||||
if vote_type == "upvote":
|
||||
if question.upvote(request.user):
|
||||
messages.success(request, "You upvoted this Poll😊")
|
||||
elif vote_type == "downvote":
|
||||
if question.downvote(request.user):
|
||||
messages.success(request, "You downvoted this Poll😭")
|
||||
|
||||
return redirect(reverse("polls:results", args=(question_id,)))
|
||||
|
||||
|
||||
# https://stackoverflow.com/questions/4581789/how-do-i-get-user-ip-address-in-django
|
||||
def get_client_ip(request):
|
||||
x_forwarded_for = request.META.get('HTTP_X_FORWARDED_FOR')
|
||||
|
||||
Loading…
Reference in New Issue
Block a user