From fc89f4e4298d448560240090c77bb8c6200ec957 Mon Sep 17 00:00:00 2001 From: Lucas Schumacher Date: Tue, 21 May 2024 00:47:26 -0400 Subject: [PATCH] Add poll app from official tutorial --- djangoTest/settings.py | 1 + djangoTest/urls.py | 1 + polls/__init__.py | 0 polls/admin.py | 6 + polls/apps.py | 6 + polls/migrations/0001_initial.py | 32 ++ polls/migrations/__init__.py | 0 polls/models.py | 18 ++ polls/templates/polls/bootstraplist.html | 386 +++++++++++++++++++++++ polls/templates/polls/detail.html | 86 +++++ polls/templates/polls/index.html | 45 +++ polls/templates/polls/listform.html | 94 ++++++ polls/templates/polls/results.html | 92 ++++++ polls/tests.py | 3 + polls/urls.py | 15 + polls/views.py | 41 +++ 16 files changed, 826 insertions(+) create mode 100644 polls/__init__.py create mode 100644 polls/admin.py create mode 100644 polls/apps.py create mode 100644 polls/migrations/0001_initial.py create mode 100644 polls/migrations/__init__.py create mode 100644 polls/models.py create mode 100644 polls/templates/polls/bootstraplist.html create mode 100644 polls/templates/polls/detail.html create mode 100644 polls/templates/polls/index.html create mode 100644 polls/templates/polls/listform.html create mode 100644 polls/templates/polls/results.html create mode 100644 polls/tests.py create mode 100644 polls/urls.py create mode 100644 polls/views.py diff --git a/djangoTest/settings.py b/djangoTest/settings.py index f8e8436..a48c2f6 100644 --- a/djangoTest/settings.py +++ b/djangoTest/settings.py @@ -31,6 +31,7 @@ ALLOWED_HOSTS = [] # Application definition INSTALLED_APPS = [ + 'polls.apps.PollsConfig', 'testapp.apps.TestappConfig', 'django.contrib.admin', 'django.contrib.auth', diff --git a/djangoTest/urls.py b/djangoTest/urls.py index 4357a88..aee2da7 100644 --- a/djangoTest/urls.py +++ b/djangoTest/urls.py @@ -20,6 +20,7 @@ from django.urls import include, path urlpatterns = [ # Add the path that our testapp should be served at path("", include("testapp.urls")), + path('polls/', include('polls.urls')), path('admin/', admin.site.urls), ] diff --git a/polls/__init__.py b/polls/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/polls/admin.py b/polls/admin.py new file mode 100644 index 0000000..b849df4 --- /dev/null +++ b/polls/admin.py @@ -0,0 +1,6 @@ +from django.contrib import admin +from . import models + +# Register your models here. +admin.site.register(models.Question) +admin.site.register(models.Choice) diff --git a/polls/apps.py b/polls/apps.py new file mode 100644 index 0000000..5a5f94c --- /dev/null +++ b/polls/apps.py @@ -0,0 +1,6 @@ +from django.apps import AppConfig + + +class PollsConfig(AppConfig): + default_auto_field = 'django.db.models.BigAutoField' + name = 'polls' diff --git a/polls/migrations/0001_initial.py b/polls/migrations/0001_initial.py new file mode 100644 index 0000000..6832600 --- /dev/null +++ b/polls/migrations/0001_initial.py @@ -0,0 +1,32 @@ +# Generated by Django 4.2.11 on 2024-05-20 03:56 + +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + initial = True + + dependencies = [ + ] + + operations = [ + migrations.CreateModel( + name='Question', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('question_text', models.CharField(max_length=200)), + ('pub_date', models.DateTimeField(verbose_name='date published')), + ], + ), + migrations.CreateModel( + name='Choice', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('choice_text', models.CharField(max_length=200)), + ('votes', models.IntegerField(default=0)), + ('question', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='polls.question')), + ], + ), + ] diff --git a/polls/migrations/__init__.py b/polls/migrations/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/polls/models.py b/polls/models.py new file mode 100644 index 0000000..c8d14de --- /dev/null +++ b/polls/models.py @@ -0,0 +1,18 @@ +from django.db import models + +# Create your models here. +class Question(models.Model): + question_text = models.CharField(max_length=200) + pub_date = models.DateTimeField("date published") + def __str__(self): + return self.question_text + def was_published_recently(self): + return self.pub_date >= timezone.now() - datetime.timedelta(days=1) + + +class Choice(models.Model): + question = models.ForeignKey(Question, on_delete=models.CASCADE) + choice_text = models.CharField(max_length=200) + votes = models.IntegerField(default=0) + def __str__(self): + return self.choice_text \ No newline at end of file diff --git a/polls/templates/polls/bootstraplist.html b/polls/templates/polls/bootstraplist.html new file mode 100644 index 0000000..1081d5a --- /dev/null +++ b/polls/templates/polls/bootstraplist.html @@ -0,0 +1,386 @@ + + + + + + + + + + List groups · Bootstrap v5.3 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+ +
+
+ + + +
+ +
+ + + +
+
+ +
+ +
+
+ + + + +
+
+ +
+ +
+
+ + + + + + + + + + + +
+
+ +
+ +
+
+
+ + +
+ +
+ + +
+ +
+ + +
+ +
+ + +
+
+
+ + + + diff --git a/polls/templates/polls/detail.html b/polls/templates/polls/detail.html new file mode 100644 index 0000000..68a65fc --- /dev/null +++ b/polls/templates/polls/detail.html @@ -0,0 +1,86 @@ + + + + + + + + Testapp + + + +
+

{{ question.question_text }}

+
+ +
+ {% csrf_token %} +
+ {% if error_message %}

{{ error_message }}

{% endif %} +
+ {% for choice in question.choice_set.all %} + +
+ {% endfor %} +
+
+
+ +
+
+ + \ No newline at end of file diff --git a/polls/templates/polls/index.html b/polls/templates/polls/index.html new file mode 100644 index 0000000..30ffbc6 --- /dev/null +++ b/polls/templates/polls/index.html @@ -0,0 +1,45 @@ + + + + + + + + + Testapp + + + +
+

Polls

+
+
+ {% if latest_question_list %} +
+ {% for question in latest_question_list %} + + +
+
+
{{ question.question_text }}
+ +
+ {{ question.pub_date }} +
+
+ {% endfor %} +
+ {% else %} +

+ No polls are available.
+ You can create polls in the admin panel +

+ {% endif %} +
+
+ + \ No newline at end of file diff --git a/polls/templates/polls/listform.html b/polls/templates/polls/listform.html new file mode 100644 index 0000000..f1591cd --- /dev/null +++ b/polls/templates/polls/listform.html @@ -0,0 +1,94 @@ + + + + + + + + + + List groups · Bootstrap v5.3 + + + + + + + + +
+
+ + + + + + + + + + + +
+
+ + diff --git a/polls/templates/polls/results.html b/polls/templates/polls/results.html new file mode 100644 index 0000000..9e9eab1 --- /dev/null +++ b/polls/templates/polls/results.html @@ -0,0 +1,92 @@ + + + + + + + + Testapp + + + +
+

{{ question.question_text }}

+
+

Results

+
+
+ {% for choice_text, choice_votes, choice_percent in choices %} +
+
+
+
{{ choice_text }}
+ +
+ + {{ choice_votes }} vote{{ choice_votes|pluralize }} +
+
+ {% endfor %} + +
+
+ + \ No newline at end of file diff --git a/polls/tests.py b/polls/tests.py new file mode 100644 index 0000000..7ce503c --- /dev/null +++ b/polls/tests.py @@ -0,0 +1,3 @@ +from django.test import TestCase + +# Create your tests here. diff --git a/polls/urls.py b/polls/urls.py new file mode 100644 index 0000000..b238746 --- /dev/null +++ b/polls/urls.py @@ -0,0 +1,15 @@ +from django.urls import path + +from . import views + +app_name = "polls" + +urlpatterns = [ + path("", views.index, name="polls-index"), + # ex: /polls/5/ + path("/", views.detail, name="detail"), + # ex: /polls/5/results/ + path("/results/", views.results, name="results"), + # ex: /polls/5/vote/ + path("/vote/", views.vote, name="vote"), +] \ No newline at end of file diff --git a/polls/views.py b/polls/views.py new file mode 100644 index 0000000..0059d0e --- /dev/null +++ b/polls/views.py @@ -0,0 +1,41 @@ +from django.shortcuts import render, get_object_or_404 +from django.http import HttpResponse, HttpResponseRedirect +from django.urls import reverse +from django.db.models import F + +from .models import Question, Choice +# Create your views here. + +def index(request): + latest_question_list = Question.objects.order_by("-pub_date")[:5] + context = {"latest_question_list": latest_question_list} + return render(request, "polls/index.html", context) + +def detail(request, question_id): + question = get_object_or_404(Question, pk=question_id) + return render(request, "polls/detail.html", {"question": question}) + + +def results(request, question_id): + question = get_object_or_404(Question, pk=question_id) + # get all the choices and their votes + choices = question.choice_set.all() + max = 0 + for choice in choices: + if choice.votes > max: + max = choice.votes + choice_data = [(choice.choice_text, choice.votes, choice.votes / max * 100) for choice in choices] + return render(request, "polls/results.html", {"question": question, "max_votes": max, "choices": choice_data}) + + +def vote(request, question_id): + question = get_object_or_404(Question, pk=question_id) + try: + selected_choice = question.choice_set.get(pk=request.POST["choice"]) + except (KeyError, Choice.DoesNotExist): + return render(request, "polls/detail.html", + {"question": question, "error_message": "You didn't select a choice."}) + else: + selected_choice.votes = F("votes") + 1 + selected_choice.save() + return HttpResponseRedirect(reverse("polls:results", args=(question.id,))) \ No newline at end of file