1st commit

This commit is contained in:
2026-05-25 19:45:43 -03:00
commit 55087c8278
44 changed files with 1522 additions and 0 deletions

0
polls/__init__.py Normal file
View File

29
polls/admin.py Normal file
View File

@@ -0,0 +1,29 @@
from django.contrib import admin
from .models import Poll, Choice, Vote
class ChoiceInline(admin.TabularInline): # or admin.StackedInline for a different layout
model = Choice
extra = 1
@admin.register(Poll)
class PollAdmin(admin.ModelAdmin):
list_display = ["text", "owner", "pub_date", "active", "created_at"]
search_fields = ["text", "owner__username"]
list_filter = ["active", 'created_at', 'pub_date']
date_hierarchy = "pub_date"
inlines = [ChoiceInline]
@admin.register(Choice)
class ChoiceAdmin(admin.ModelAdmin):
list_display = ["choice_text", "poll", 'created_at', 'updated_at']
search_fields = ["choice_text", "poll__text"]
autocomplete_fields = ["poll"]
@admin.register(Vote)
class VoteAdmin(admin.ModelAdmin):
list_display = ["choice", "poll", "user", 'created_at']
search_fields = ["choice__choice_text", "poll__text", "user__username"]
autocomplete_fields = ["choice", "poll", "user"]

5
polls/apps.py Normal file
View File

@@ -0,0 +1,5 @@
from django.apps import AppConfig
class PollsConfig(AppConfig):
name = 'polls'

35
polls/forms.py Normal file
View File

@@ -0,0 +1,35 @@
from django import forms
from .models import Poll, Choice
class PollAddForm(forms.ModelForm):
choice1 = forms.CharField(label='Choice 1', max_length=100, min_length=1,
widget=forms.TextInput(attrs={'class': 'form-control'}))
choice2 = forms.CharField(label='Choice 2', max_length=100, min_length=1,
widget=forms.TextInput(attrs={'class': 'form-control'}))
class Meta:
model = Poll
fields = ['text', 'choice1', 'choice2']
widgets = {
'text': forms.Textarea(attrs={'class': 'form-control', 'rows': 5, 'cols': 20}),
}
class EditPollForm(forms.ModelForm):
class Meta:
model = Poll
fields = ['text', ]
widgets = {
'text': forms.Textarea(attrs={'class': 'form-control', 'rows': 5, 'cols': 20}),
}
class ChoiceAddForm(forms.ModelForm):
class Meta:
model = Choice
fields = ['choice_text', ]
widgets = {
'choice_text': forms.TextInput(attrs={'class': 'form-control', })
}

View File

@@ -0,0 +1,49 @@
# Generated by Django 3.1.5 on 2021-01-29 16:38
from django.conf import settings
from django.db import migrations, models
import django.db.models.deletion
import django.utils.timezone
class Migration(migrations.Migration):
initial = True
dependencies = [
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
]
operations = [
migrations.CreateModel(
name='Choice',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('choice_text', models.CharField(max_length=255)),
],
),
migrations.CreateModel(
name='Poll',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('text', models.TextField()),
('pub_date', models.DateTimeField(default=django.utils.timezone.now)),
('active', models.BooleanField(default=True)),
('owner', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)),
],
),
migrations.CreateModel(
name='Vote',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('choice', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='polls.choice')),
('poll', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='polls.poll')),
('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)),
],
),
migrations.AddField(
model_name='choice',
name='poll',
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='polls.poll'),
),
]

View File

@@ -0,0 +1,42 @@
# Generated by Django 3.1.14 on 2023-10-18 07:18
from django.db import migrations, models
import django.utils.timezone
class Migration(migrations.Migration):
dependencies = [
('polls', '0001_initial'),
]
operations = [
migrations.AddField(
model_name='choice',
name='created_at',
field=models.DateTimeField(auto_now_add=True, default=django.utils.timezone.now),
preserve_default=False,
),
migrations.AddField(
model_name='choice',
name='updated_at',
field=models.DateTimeField(auto_now=True),
),
migrations.AddField(
model_name='poll',
name='created_at',
field=models.DateTimeField(auto_now_add=True, default=django.utils.timezone.now),
preserve_default=False,
),
migrations.AddField(
model_name='vote',
name='created_at',
field=models.DateTimeField(auto_now_add=True, default=django.utils.timezone.now),
preserve_default=False,
),
migrations.AddField(
model_name='vote',
name='updated_at',
field=models.DateTimeField(auto_now=True),
),
]

View File

73
polls/models.py Normal file
View File

@@ -0,0 +1,73 @@
from django.contrib.auth.models import User
from django.db import models
from django.utils import timezone
import secrets
class Poll(models.Model):
owner = models.ForeignKey(User, on_delete=models.CASCADE)
text = models.TextField()
pub_date = models.DateTimeField(default=timezone.now)
active = models.BooleanField(default=True)
created_at = models.DateTimeField(auto_now_add=True)
def user_can_vote(self, user):
"""
Return False if user already voted
"""
user_votes = user.vote_set.all()
qs = user_votes.filter(poll=self)
if qs.exists():
return False
return True
@property
def get_vote_count(self):
return self.vote_set.count()
def get_result_dict(self):
res = []
for choice in self.choice_set.all():
d = {}
alert_class = ['primary', 'secondary', 'success',
'danger', 'dark', 'warning', 'info']
d['alert_class'] = secrets.choice(alert_class)
d['text'] = choice.choice_text
d['num_votes'] = choice.get_vote_count
if not self.get_vote_count:
d['percentage'] = 0
else:
d['percentage'] = (choice.get_vote_count /
self.get_vote_count)*100
res.append(d)
return res
def __str__(self):
return self.text
class Choice(models.Model):
poll = models.ForeignKey(Poll, on_delete=models.CASCADE)
choice_text = models.CharField(max_length=255)
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
@property
def get_vote_count(self):
return self.vote_set.count()
def __str__(self):
return f"{self.poll.text[:25]} - {self.choice_text[:25]}"
class Vote(models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE)
poll = models.ForeignKey(Poll, on_delete=models.CASCADE)
choice = models.ForeignKey(Choice, on_delete=models.CASCADE)
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
def __str__(self):
return f'{self.poll.text[:15]} - {self.choice.choice_text[:15]} - {self.user.username}'

View File

@@ -0,0 +1,38 @@
{% extends 'base.html' %}
{% block content %}
<div class="container">
<div class="row center">
<div class="col-md-6 offset-md-3">
{% if edit_choice %}
<h2>Update choice</h2>
{% else %}
<h2>Add new choice</h2>
{% endif %}
{% if messages %}
<ul class="messages">
{% for message in messages %}
<li {% if message.tags %} class="{{ message.tags }}" {% endif %}>{{ message }}</li>
{% endfor %}
</ul>
{% endif %}
<form action="" method="POST">
{% csrf_token %}
{% for field in form %}
<div class="form-group">
{{ field.errors }}
{{ field.label_tag }}
{{ field }}
</div>
{% endfor %}
{% if edit_choice %}
<button type="submit" class="btn btn-primary">Update</button>
<a class="btn btn-danger" href="{% url 'polls:choice_delete' choice.id %}" role="button" onclick="return confirm('Are you sure you want to delete this?')">Delete</a>
{% else %}
<button type="submit" class="btn btn-primary">Add</button>
{% endif %}
</form>
</div>
</div>
</div>
{% endblock %}

View File

@@ -0,0 +1,30 @@
{% extends 'base.html' %}
{% block content %}
<div class="container">
<div class="row center">
<div class="col-md-6 offset-md-3">
<h2>Create new poll</h2>
{% if messages %}
<ul class="messages">
{% for message in messages %}
<li {% if message.tags %} class="{{ message.tags }}" {% endif %}>{{ message }}</li>
{% endfor %}
</ul>
{% endif %}
<form action="" method="POST">
{% csrf_token %}
{% for field in form %}
<div class="form-group">
{{ field.errors }}
{{ field.label_tag }}
{{ field }}
</div>
{% endfor %}
<button type="submit" class="btn btn-primary">Add Poll</button>
<a class="btn btn-warning" href="{% url 'polls:list' %}" role="button">Back</a>
</form>
</div>
</div>
</div>
{% endblock %}

View File

@@ -0,0 +1,43 @@
{% extends 'base.html' %}
{% block content %}
<div class="container">
{% if messages %}
<div class="messages">
{% for message in messages %}
<div {% if message.tags %} class="{{ message.tags }}" {% endif %}>{{ message }}
<button type="button" class="close" data-dismiss="alert" aria-label="Close">
<span aria-hidden="true">&times;</span>
</button>
</div>
{% endfor %}
</div>
{% else %}
<div class="row">
<div class="col-md-8 offset-sm-2">
<h3 class="mt-3 mb-3 text-center">Result for: {{ poll.text }}</h3>
<!-- progress bar -->
<div class="progress mt-3">
{% for choice in poll.get_result_dict %}
<div class="progress-bar bg-{{ choice.alert_class }}" role="progressbar" style="width: {{ choice.percentage }}%;" aria-valuenow="30" aria-valuemin="0"
aria-valuemax="100"><b>{{ choice.text }}-{{ choice.percentage|floatformat }}%</b></div>
{% endfor %}
</div>
<ul class="list-group">
{% for choice in poll.choice_set.all %}
<li class="list-group-item d-flex justify-content-between align-items-center">
{{ choice.choice_text }}
<span class="badge badge-primary badge-pill">{{ choice.get_vote_count }}</span>
</li>
{% endfor %}
</ul>
{% endif %}
<a class="btn btn-primary mt-3" href="{% url 'polls:list' %}" role="button">Back To Polls</a>
</div>
</div>
</div>
{% endblock content %}

View File

@@ -0,0 +1,33 @@
{% extends 'base.html' %}
{% block content %}
<div class="container">
<h1>Polls details page</h1>
{% if messages %}
<div class="messages">
{% for message in messages %}
<div {% if message.tags %} class="{{ message.tags }}" {% endif %}>{{ message }}
<button type="button" class="close" data-dismiss="alert" aria-label="Close">
<span aria-hidden="true">&times;</span>
</button>
</div>
{% endfor %}
</div>
{% endif %}
<hr>
<h2 class="mt-3 mb-3">{{ poll }}</h2>
<form action="{% url 'polls:vote' poll.id %}" method="POST">
{% csrf_token %}
{% for choice in poll.choice_set.all %}
<input type="radio" name="choice" id="choice{{ forloop.counter }}" value="{{ choice.id }}">
<label for="choice{{ forloop.counter }}">{{ choice.choice_text }}</label>
<br>
{% endfor %}
<input type="submit" value="Vote" class="btn btn-primary mt-3">
<a class="btn btn-warning mt-3" href="{% url 'polls:list' %}" role="button">Cancel</a>
</form>
</div>
{% endblock content %}

View File

@@ -0,0 +1,49 @@
{% extends 'base.html' %}
{% block content %}
<div class="container">
<div class="row center">
<div class="col-md-6 offset-md-3">
<h2>Edit poll</h2>
{% if messages %}
{% if messages %}
<div class="messages">
{% for message in messages %}
<div {% if message.tags %} class="{{ message.tags }}" {% endif %}>{{ message }}
<button type="button" class="close" data-dismiss="alert" aria-label="Close">
<span aria-hidden="true">&times;</span>
</button>
</div>
{% endfor %}
</div>
{% endif %}
{% endif %}
<form action="" method="POST">
{% csrf_token %}
{% for field in form %}
<div class="form-group">
{{ field.errors }}
{{ field.label_tag }}
{{ field }}
</div>
{% endfor %}
<button type="submit" class="btn btn-primary">Update</button>
<a class="btn btn-danger" href="{% url 'polls:delete_poll' poll.id %}" role="button" onclick="return confirm('Are you sure?')">Delete</a>
<a class="btn btn-warning" href="{% url 'polls:add_choice' poll.id %}" role="button">Add Choice</a>
</form>
<div class="choices">
<h2 class="text-center mt-3">Choices</h2>
<hr>
<ul class="list-group">
{% for choice in poll.choice_set.all %}
<li class="list-group-item"><a href="{% url 'polls:choice_edit' choice.id %}"><i class="fas fa-pencil-alt"></i></a>&nbsp
{{ choice.choice_text }}</li>
{% endfor %}
</ul>
</div>
</div>
</div>
</div>
{% endblock %}

View File

@@ -0,0 +1,48 @@
{% extends 'base.html' %}
{% block content %}
<div class="container">
{% if messages %}
<div class="messages">
{% for message in messages %}
<div {% if message.tags %} class="{{ message.tags }}" {% endif %}>{{ message }}
<button type="button" class="close" data-dismiss="alert" aria-label="Close">
<span aria-hidden="true">&times;</span>
</button>
</div>
{% endfor %}
</div>
{% else %}
<div class="row">
<div class="col-md-8 offset-sm-2">
{% if poll.active %}
<h3 class="mt-3 mb-3 text-center">Result for: {{ poll.text }}</h3>
{% else %}
<h3 class="mt-3 mb-3 text-center">"{{ poll.text }}" Has Ended Polling!</h3>
{% endif %}
<h3 class="mb-2 text-center">Total: {{ poll.get_vote_count }} votes</h3>
<!-- progress bar -->
<div class="progress mt-3 mb-2">
{% for choice in poll.get_result_dict %}
<div class="progress-bar bg-{{ choice.alert_class }}" role="progressbar" style="width: {{ choice.percentage }}%;"
aria-valuenow="30" aria-valuemin="0" aria-valuemax="100"><b>
{{choice.text|truncatewords:2}}-{{choice.percentage|floatformat}}%</b>
</div>
{% endfor %}
</div>
<ul class="list-group">
{% for choice in poll.choice_set.all %}
<li class="list-group-item d-flex justify-content-between align-items-center">
{{ choice.choice_text }}
<span class="badge badge-primary badge-pill">{{ choice.get_vote_count }}</span>
</li>
{% endfor %}
</ul>
{% endif %}
<a class="btn btn-primary mt-3" href="{% url 'polls:list' %}" role="button">Back To Polls</a>
</div>
</div>
</div>
{% endblock content %}

View File

@@ -0,0 +1,78 @@
{% extends 'base.html' %}
{% block content %}
<div class="container">
<div class="row">
<div class="col-md-8 offset-sm-2">
<h1 class="text-center mb-5">Welcome to polls List!</h1>
{% if messages %}
<div class="messages">
{% for message in messages %}
<div {% if message.tags %} class="{{ message.tags }}" {% endif %}>{{ message }}
<button type="button" class="close" data-dismiss="alert" aria-label="Close">
<span aria-hidden="true">&times;</span>
</button>
</div>
{% endfor %}
</div>
{% endif %}
<a class="btn btn-{% if 'name' in request.GET %}warning{% else %}primary{% endif %} mb-3" href="?name=True"
role="button"><i class="fas fa-sort-alpha-down"></i>
Name</a>
<a class="btn btn-{% if 'date' in request.GET %}warning{% else %}primary{% endif %} mb-3" href="?date=True"
role="button"><i class="far fa-clock"></i> Date</a>
<a class="btn btn-{% if 'vote' in request.GET %}warning{% else %}primary{% endif %} mb-3" href="?vote=True"
role="button"><i class="fas fa-poll"></i> Vote</a>
<a class="btn btn-primary mb-3 float-right" href="{% url 'polls:add' %}" role="button">Add <i class="fas fa-plus"></i></a>
<form class="form-inline">
<div class="form-group mr-sm-2 mb-2">
<input type="search" class="form-control" name="search" placeholder="Search" value={{ search_term }}>
</div>
<button type="submit" class="btn btn-primary mb-2"><i class="fas fa-search"></i></button>
</form>
<ul class="list-group">
{% for poll in polls %}
<li class="list-group-item"><a href="{% url 'polls:detail' poll.id %}">{{ poll.text|truncatewords:5 }}
{% if not poll.active%}
<i class="fas fa-check-circle ml-2"></i>
{% endif %}
</a>
{% if request.user == poll.owner %}
{% if poll.active %}
<a href="{% url 'polls:end_poll' poll.id %}" data-toggle="tooltip" data-placement="top" title="End Poll"
onclick="return confirm('Are you sure ?')"><i class="fas fa-step-forward float-right btn btn-danger btn-sm"></i></a>
{% endif %}
<a href="{% url 'polls:edit' poll.id %}" class="mr-3" data-toggle="tooltip" data-placement="top"
title="Edit Poll"><i class="fas fa-pencil-alt float-right btn btn-primary btn-sm mr-1"></i></a>
{% endif %}
</li>
{% endfor %}
</ul>
{% if polls.paginator.num_pages > 1 %}
<nav class="mt-3">
<ul class="pagination">
{% if polls.has_previous %}
<li class="page-item"><a class="page-link" href="?page=1&{{ params }}">First</a></li>
<li class="page-item"><a class="page-link" href="?page={{ polls.previous_page_number }}&{{ params }}">Previous</a></li>
{% endif %}
<li class="page-item active"><a class="page-link" href="">{{ polls.number }}</a></li>
{% if polls.has_next %}
<li class="page-item"><a class="page-link" href="?page={{ polls.next_page_number }}&{{ params }}">Next</a></li>
<li class="page-item"><a class="page-link" href="?page={{ polls.paginator.num_pages }}&{{ params }}">Last</a></li>
{% endif %}
</ul>
</nav>
{% endif %}
</div>
</div>
</div>
{% endblock content %}

44
polls/tests.py Normal file
View File

@@ -0,0 +1,44 @@
from django.contrib.auth import authenticate
from django.contrib.auth.models import User
from django.test import TestCase
from django.utils import timezone
from .models import Poll, Vote
class PollModelTest(TestCase):
def test_user_can_vote(self):
user = User.objects.create_user('john')
poll = Poll.objects.create(owner=user)
self.assertTrue(poll.user_can_vote(user))
choice = poll.choice_set.create(choice_text='pizza')
Vote.objects.create(user=user, poll=poll, choice=choice)
self.assertFalse(poll.user_can_vote(user))
class PollViewTest(TestCase):
def test_home(self):
response = self.client.get('/')
self.assertEqual(response.status_code, 200)
def test_login(self):
User.objects.create_user(username='john', password='rambo')
response = self.client.post(
'/accounts/login/', {'username': 'john', 'password': 'rambo'}
)
self.assertRedirects(response, '/')
def test_register(self):
response = self.client.post(
'/accounts/register/',
{
'username': 'johny',
'password1': 'rambo',
'password2': 'rambo',
'email': 'johny.rambo@usarmy.gov',
},
)
self.assertRedirects(response, '/accounts/login/')
# assert that user got actually created in the backend
self.assertIsNotNone(authenticate(username='johny', password='rambo'))

19
polls/urls.py Normal file
View File

@@ -0,0 +1,19 @@
from django.urls import path
from . import views
app_name = "polls"
urlpatterns = [
path('list/', views.polls_list, name='list'),
path('list/user/', views.list_by_user, name='list_by_user'),
path('add/', views.polls_add, name='add'),
path('edit/<int:poll_id>/', views.polls_edit, name='edit'),
path('delete/<int:poll_id>/', views.polls_delete, name='delete_poll'),
path('end/<int:poll_id>/', views.end_poll, name='end_poll'),
path('edit/<int:poll_id>/choice/add/', views.add_choice, name='add_choice'),
path('edit/choice/<int:choice_id>/', views.choice_edit, name='choice_edit'),
path('delete/choice/<int:choice_id>/',
views.choice_delete, name='choice_delete'),
path('<int:poll_id>/', views.poll_detail, name='detail'),
path('<int:poll_id>/vote/', views.poll_vote, name='vote'),
]

223
polls/views.py Normal file
View File

@@ -0,0 +1,223 @@
from django.shortcuts import render, get_object_or_404, redirect
from django.contrib.auth.decorators import login_required
from django.core.paginator import Paginator
from django.db.models import Count
from django.contrib import messages
from .models import Poll, Choice, Vote
from .forms import PollAddForm, EditPollForm, ChoiceAddForm
from django.http import HttpResponse
@login_required()
def polls_list(request):
all_polls = Poll.objects.all()
search_term = ''
if 'name' in request.GET:
all_polls = all_polls.order_by('text')
if 'date' in request.GET:
all_polls = all_polls.order_by('pub_date')
if 'vote' in request.GET:
all_polls = all_polls.annotate(Count('vote')).order_by('vote__count')
if 'search' in request.GET:
search_term = request.GET['search']
all_polls = all_polls.filter(text__icontains=search_term)
paginator = Paginator(all_polls, 6) # Show 6 contacts per page
page = request.GET.get('page')
polls = paginator.get_page(page)
get_dict_copy = request.GET.copy()
params = get_dict_copy.pop('page', True) and get_dict_copy.urlencode()
context = {
'polls': polls,
'params': params,
'search_term': search_term,
}
return render(request, 'polls/polls_list.html', context)
@login_required()
def list_by_user(request):
all_polls = Poll.objects.filter(owner=request.user)
paginator = Paginator(all_polls, 7) # Show 7 contacts per page
page = request.GET.get('page')
polls = paginator.get_page(page)
context = {
'polls': polls,
}
return render(request, 'polls/polls_list.html', context)
@login_required()
def polls_add(request):
if request.user.has_perm('polls.add_poll'):
if request.method == 'POST':
form = PollAddForm(request.POST)
if form.is_valid:
poll = form.save(commit=False)
poll.owner = request.user
poll.save()
Choice(
poll=poll, choice_text=form.cleaned_data['choice1']).save()
Choice(
poll=poll, choice_text=form.cleaned_data['choice2']).save()
messages.success(
request, "Poll & Choices added successfully.", extra_tags='alert alert-success alert-dismissible fade show')
return redirect('polls:list')
else:
form = PollAddForm()
context = {
'form': form,
}
return render(request, 'polls/add_poll.html', context)
else:
return HttpResponse("Sorry but you don't have permission to do that!")
@login_required
def polls_edit(request, poll_id):
poll = get_object_or_404(Poll, pk=poll_id)
if request.user != poll.owner:
return redirect('home')
if request.method == 'POST':
form = EditPollForm(request.POST, instance=poll)
if form.is_valid:
form.save()
messages.success(request, "Poll Updated successfully.",
extra_tags='alert alert-success alert-dismissible fade show')
return redirect("polls:list")
else:
form = EditPollForm(instance=poll)
return render(request, "polls/poll_edit.html", {'form': form, 'poll': poll})
@login_required
def polls_delete(request, poll_id):
poll = get_object_or_404(Poll, pk=poll_id)
if request.user != poll.owner:
return redirect('home')
poll.delete()
messages.success(request, "Poll Deleted successfully.",
extra_tags='alert alert-success alert-dismissible fade show')
return redirect("polls:list")
@login_required
def add_choice(request, poll_id):
poll = get_object_or_404(Poll, pk=poll_id)
if request.user != poll.owner:
return redirect('home')
if request.method == 'POST':
form = ChoiceAddForm(request.POST)
if form.is_valid:
new_choice = form.save(commit=False)
new_choice.poll = poll
new_choice.save()
messages.success(
request, "Choice added successfully.", extra_tags='alert alert-success alert-dismissible fade show')
return redirect('polls:edit', poll.id)
else:
form = ChoiceAddForm()
context = {
'form': form,
}
return render(request, 'polls/add_choice.html', context)
@login_required
def choice_edit(request, choice_id):
choice = get_object_or_404(Choice, pk=choice_id)
poll = get_object_or_404(Poll, pk=choice.poll.id)
if request.user != poll.owner:
return redirect('home')
if request.method == 'POST':
form = ChoiceAddForm(request.POST, instance=choice)
if form.is_valid:
new_choice = form.save(commit=False)
new_choice.poll = poll
new_choice.save()
messages.success(
request, "Choice Updated successfully.", extra_tags='alert alert-success alert-dismissible fade show')
return redirect('polls:edit', poll.id)
else:
form = ChoiceAddForm(instance=choice)
context = {
'form': form,
'edit_choice': True,
'choice': choice,
}
return render(request, 'polls/add_choice.html', context)
@login_required
def choice_delete(request, choice_id):
choice = get_object_or_404(Choice, pk=choice_id)
poll = get_object_or_404(Poll, pk=choice.poll.id)
if request.user != poll.owner:
return redirect('home')
choice.delete()
messages.success(
request, "Choice Deleted successfully.", extra_tags='alert alert-success alert-dismissible fade show')
return redirect('polls:edit', poll.id)
def poll_detail(request, poll_id):
poll = get_object_or_404(Poll, id=poll_id)
if not poll.active:
return render(request, 'polls/poll_result.html', {'poll': poll})
loop_count = poll.choice_set.count()
context = {
'poll': poll,
'loop_time': range(0, loop_count),
}
return render(request, 'polls/poll_detail.html', context)
@login_required
def poll_vote(request, poll_id):
poll = get_object_or_404(Poll, pk=poll_id)
choice_id = request.POST.get('choice')
if not poll.user_can_vote(request.user):
messages.error(
request, "You already voted this poll!", extra_tags='alert alert-warning alert-dismissible fade show')
return redirect("polls:list")
if choice_id:
choice = Choice.objects.get(id=choice_id)
vote = Vote(user=request.user, poll=poll, choice=choice)
vote.save()
print(vote)
return render(request, 'polls/poll_result.html', {'poll': poll})
else:
messages.error(
request, "No choice selected!", extra_tags='alert alert-warning alert-dismissible fade show')
return redirect("polls:detail", poll_id)
return render(request, 'polls/poll_result.html', {'poll': poll})
@login_required
def end_poll(request, poll_id):
poll = get_object_or_404(Poll, pk=poll_id)
if request.user != poll.owner:
return redirect('home')
if poll.active is True:
poll.active = False
poll.save()
return render(request, 'polls/poll_result.html', {'poll': poll})
else:
return render(request, 'polls/poll_result.html', {'poll': poll})