Add poll app from official tutorial
This commit is contained in:
parent
5f2bc11155
commit
fc89f4e429
@ -31,6 +31,7 @@ ALLOWED_HOSTS = []
|
|||||||
# Application definition
|
# Application definition
|
||||||
|
|
||||||
INSTALLED_APPS = [
|
INSTALLED_APPS = [
|
||||||
|
'polls.apps.PollsConfig',
|
||||||
'testapp.apps.TestappConfig',
|
'testapp.apps.TestappConfig',
|
||||||
'django.contrib.admin',
|
'django.contrib.admin',
|
||||||
'django.contrib.auth',
|
'django.contrib.auth',
|
||||||
|
|||||||
@ -20,6 +20,7 @@ from django.urls import include, path
|
|||||||
urlpatterns = [
|
urlpatterns = [
|
||||||
# Add the path that our testapp should be served at
|
# Add the path that our testapp should be served at
|
||||||
path("", include("testapp.urls")),
|
path("", include("testapp.urls")),
|
||||||
|
path('polls/', include('polls.urls')),
|
||||||
|
|
||||||
path('admin/', admin.site.urls),
|
path('admin/', admin.site.urls),
|
||||||
]
|
]
|
||||||
|
|||||||
0
polls/__init__.py
Normal file
0
polls/__init__.py
Normal file
6
polls/admin.py
Normal file
6
polls/admin.py
Normal file
@ -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)
|
||||||
6
polls/apps.py
Normal file
6
polls/apps.py
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
from django.apps import AppConfig
|
||||||
|
|
||||||
|
|
||||||
|
class PollsConfig(AppConfig):
|
||||||
|
default_auto_field = 'django.db.models.BigAutoField'
|
||||||
|
name = 'polls'
|
||||||
32
polls/migrations/0001_initial.py
Normal file
32
polls/migrations/0001_initial.py
Normal file
@ -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')),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
]
|
||||||
0
polls/migrations/__init__.py
Normal file
0
polls/migrations/__init__.py
Normal file
18
polls/models.py
Normal file
18
polls/models.py
Normal file
@ -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
|
||||||
386
polls/templates/polls/bootstraplist.html
Normal file
386
polls/templates/polls/bootstraplist.html
Normal file
@ -0,0 +1,386 @@
|
|||||||
|
<!doctype html>
|
||||||
|
<html lang="en" data-bs-theme="auto">
|
||||||
|
<head><script src="https://getbootstrap.com/docs/5.3/assets/js/color-modes.js"></script>
|
||||||
|
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
|
<meta name="description" content="">
|
||||||
|
<meta name="author" content="Mark Otto, Jacob Thornton, and Bootstrap contributors">
|
||||||
|
<meta name="generator" content="Hugo 0.122.0">
|
||||||
|
<title>List groups · Bootstrap v5.3</title>
|
||||||
|
|
||||||
|
<link rel="canonical" href="https://getbootstrap.com/docs/5.3/examples/list-groups/">
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@docsearch/css@3">
|
||||||
|
|
||||||
|
<link href="https://getbootstrap.com/docs/5.3/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-QWTKZyjpPEjISv5WaRU9OFeRpok6YctnYmDr5pNlyT2bRjXh0JMhjY6hW+ALEwIH" crossorigin="anonymous">
|
||||||
|
|
||||||
|
<!-- Favicons -->
|
||||||
|
<link rel="apple-touch-icon" href="https://getbootstrap.com/docs/5.3/assets/img/favicons/apple-touch-icon.png" sizes="180x180">
|
||||||
|
<link rel="icon" href="https://getbootstrap.com/docs/5.3/assets/img/favicons/favicon-32x32.png" sizes="32x32" type="image/png">
|
||||||
|
<link rel="icon" href="https://getbootstrap.com/docs/5.3/assets/img/favicons/favicon-16x16.png" sizes="16x16" type="image/png">
|
||||||
|
<link rel="manifest" href="https://getbootstrap.com/docs/5.3/assets/img/favicons/manifest.json">
|
||||||
|
<link rel="mask-icon" href="https://getbootstrap.com/docs/5.3/assets/img/favicons/safari-pinned-tab.svg" color="#712cf9">
|
||||||
|
<link rel="icon" href="https://getbootstrap.com/docs/5.3/assets/img/favicons/favicon.ico">
|
||||||
|
<meta name="theme-color" content="#712cf9">
|
||||||
|
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.bd-placeholder-img {
|
||||||
|
font-size: 1.125rem;
|
||||||
|
text-anchor: middle;
|
||||||
|
-webkit-user-select: none;
|
||||||
|
-moz-user-select: none;
|
||||||
|
user-select: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (min-width: 768px) {
|
||||||
|
.bd-placeholder-img-lg {
|
||||||
|
font-size: 3.5rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.b-example-divider {
|
||||||
|
width: 100%;
|
||||||
|
height: 3rem;
|
||||||
|
background-color: rgba(0, 0, 0, .1);
|
||||||
|
border: solid rgba(0, 0, 0, .15);
|
||||||
|
border-width: 1px 0;
|
||||||
|
box-shadow: inset 0 .5em 1.5em rgba(0, 0, 0, .1), inset 0 .125em .5em rgba(0, 0, 0, .15);
|
||||||
|
}
|
||||||
|
|
||||||
|
.b-example-vr {
|
||||||
|
flex-shrink: 0;
|
||||||
|
width: 1.5rem;
|
||||||
|
height: 100vh;
|
||||||
|
}
|
||||||
|
|
||||||
|
.bi {
|
||||||
|
vertical-align: -.125em;
|
||||||
|
fill: currentColor;
|
||||||
|
}
|
||||||
|
|
||||||
|
.nav-scroller {
|
||||||
|
position: relative;
|
||||||
|
z-index: 2;
|
||||||
|
height: 2.75rem;
|
||||||
|
overflow-y: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.nav-scroller .nav {
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: nowrap;
|
||||||
|
padding-bottom: 1rem;
|
||||||
|
margin-top: -1px;
|
||||||
|
overflow-x: auto;
|
||||||
|
text-align: center;
|
||||||
|
white-space: nowrap;
|
||||||
|
-webkit-overflow-scrolling: touch;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn-bd-primary {
|
||||||
|
--bd-violet-bg: #712cf9;
|
||||||
|
--bd-violet-rgb: 112.520718, 44.062154, 249.437846;
|
||||||
|
|
||||||
|
--bs-btn-font-weight: 600;
|
||||||
|
--bs-btn-color: var(--bs-white);
|
||||||
|
--bs-btn-bg: var(--bd-violet-bg);
|
||||||
|
--bs-btn-border-color: var(--bd-violet-bg);
|
||||||
|
--bs-btn-hover-color: var(--bs-white);
|
||||||
|
--bs-btn-hover-bg: #6528e0;
|
||||||
|
--bs-btn-hover-border-color: #6528e0;
|
||||||
|
--bs-btn-focus-shadow-rgb: var(--bd-violet-rgb);
|
||||||
|
--bs-btn-active-color: var(--bs-btn-hover-color);
|
||||||
|
--bs-btn-active-bg: #5a23c8;
|
||||||
|
--bs-btn-active-border-color: #5a23c8;
|
||||||
|
}
|
||||||
|
|
||||||
|
.bd-mode-toggle {
|
||||||
|
z-index: 1500;
|
||||||
|
}
|
||||||
|
|
||||||
|
.bd-mode-toggle .dropdown-menu .active .bi {
|
||||||
|
display: block !important;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
||||||
|
|
||||||
|
<!-- Custom styles for this template -->
|
||||||
|
<link href="list-groups.css" rel="stylesheet">
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" class="d-none">
|
||||||
|
<symbol id="check2" viewBox="0 0 16 16">
|
||||||
|
<path d="M13.854 3.646a.5.5 0 0 1 0 .708l-7 7a.5.5 0 0 1-.708 0l-3.5-3.5a.5.5 0 1 1 .708-.708L6.5 10.293l6.646-6.647a.5.5 0 0 1 .708 0z"/>
|
||||||
|
</symbol>
|
||||||
|
<symbol id="circle-half" viewBox="0 0 16 16">
|
||||||
|
<path d="M8 15A7 7 0 1 0 8 1v14zm0 1A8 8 0 1 1 8 0a8 8 0 0 1 0 16z"/>
|
||||||
|
</symbol>
|
||||||
|
<symbol id="moon-stars-fill" viewBox="0 0 16 16">
|
||||||
|
<path d="M6 .278a.768.768 0 0 1 .08.858 7.208 7.208 0 0 0-.878 3.46c0 4.021 3.278 7.277 7.318 7.277.527 0 1.04-.055 1.533-.16a.787.787 0 0 1 .81.316.733.733 0 0 1-.031.893A8.349 8.349 0 0 1 8.344 16C3.734 16 0 12.286 0 7.71 0 4.266 2.114 1.312 5.124.06A.752.752 0 0 1 6 .278z"/>
|
||||||
|
<path d="M10.794 3.148a.217.217 0 0 1 .412 0l.387 1.162c.173.518.579.924 1.097 1.097l1.162.387a.217.217 0 0 1 0 .412l-1.162.387a1.734 1.734 0 0 0-1.097 1.097l-.387 1.162a.217.217 0 0 1-.412 0l-.387-1.162A1.734 1.734 0 0 0 9.31 6.593l-1.162-.387a.217.217 0 0 1 0-.412l1.162-.387a1.734 1.734 0 0 0 1.097-1.097l.387-1.162zM13.863.099a.145.145 0 0 1 .274 0l.258.774c.115.346.386.617.732.732l.774.258a.145.145 0 0 1 0 .274l-.774.258a1.156 1.156 0 0 0-.732.732l-.258.774a.145.145 0 0 1-.274 0l-.258-.774a1.156 1.156 0 0 0-.732-.732l-.774-.258a.145.145 0 0 1 0-.274l.774-.258c.346-.115.617-.386.732-.732L13.863.1z"/>
|
||||||
|
</symbol>
|
||||||
|
<symbol id="sun-fill" viewBox="0 0 16 16">
|
||||||
|
<path d="M8 12a4 4 0 1 0 0-8 4 4 0 0 0 0 8zM8 0a.5.5 0 0 1 .5.5v2a.5.5 0 0 1-1 0v-2A.5.5 0 0 1 8 0zm0 13a.5.5 0 0 1 .5.5v2a.5.5 0 0 1-1 0v-2A.5.5 0 0 1 8 13zm8-5a.5.5 0 0 1-.5.5h-2a.5.5 0 0 1 0-1h2a.5.5 0 0 1 .5.5zM3 8a.5.5 0 0 1-.5.5h-2a.5.5 0 0 1 0-1h2A.5.5 0 0 1 3 8zm10.657-5.657a.5.5 0 0 1 0 .707l-1.414 1.415a.5.5 0 1 1-.707-.708l1.414-1.414a.5.5 0 0 1 .707 0zm-9.193 9.193a.5.5 0 0 1 0 .707L3.05 13.657a.5.5 0 0 1-.707-.707l1.414-1.414a.5.5 0 0 1 .707 0zm9.193 2.121a.5.5 0 0 1-.707 0l-1.414-1.414a.5.5 0 0 1 .707-.707l1.414 1.414a.5.5 0 0 1 0 .707zM4.464 4.465a.5.5 0 0 1-.707 0L2.343 3.05a.5.5 0 1 1 .707-.707l1.414 1.414a.5.5 0 0 1 0 .708z"/>
|
||||||
|
</symbol>
|
||||||
|
</svg>
|
||||||
|
|
||||||
|
<div class="dropdown position-fixed bottom-0 end-0 mb-3 me-3 bd-mode-toggle">
|
||||||
|
<button class="btn btn-bd-primary py-2 dropdown-toggle d-flex align-items-center"
|
||||||
|
id="bd-theme"
|
||||||
|
type="button"
|
||||||
|
aria-expanded="false"
|
||||||
|
data-bs-toggle="dropdown"
|
||||||
|
aria-label="Toggle theme (auto)">
|
||||||
|
<svg class="bi my-1 theme-icon-active" width="1em" height="1em"><use href="#circle-half"></use></svg>
|
||||||
|
<span class="visually-hidden" id="bd-theme-text">Toggle theme</span>
|
||||||
|
</button>
|
||||||
|
<ul class="dropdown-menu dropdown-menu-end shadow" aria-labelledby="bd-theme-text">
|
||||||
|
<li>
|
||||||
|
<button type="button" class="dropdown-item d-flex align-items-center" data-bs-theme-value="light" aria-pressed="false">
|
||||||
|
<svg class="bi me-2 opacity-50" width="1em" height="1em"><use href="#sun-fill"></use></svg>
|
||||||
|
Light
|
||||||
|
<svg class="bi ms-auto d-none" width="1em" height="1em"><use href="#check2"></use></svg>
|
||||||
|
</button>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<button type="button" class="dropdown-item d-flex align-items-center" data-bs-theme-value="dark" aria-pressed="false">
|
||||||
|
<svg class="bi me-2 opacity-50" width="1em" height="1em"><use href="#moon-stars-fill"></use></svg>
|
||||||
|
Dark
|
||||||
|
<svg class="bi ms-auto d-none" width="1em" height="1em"><use href="#check2"></use></svg>
|
||||||
|
</button>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<button type="button" class="dropdown-item d-flex align-items-center active" data-bs-theme-value="auto" aria-pressed="true">
|
||||||
|
<svg class="bi me-2 opacity-50" width="1em" height="1em"><use href="#circle-half"></use></svg>
|
||||||
|
Auto
|
||||||
|
<svg class="bi ms-auto d-none" width="1em" height="1em"><use href="#check2"></use></svg>
|
||||||
|
</button>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg" class="d-none">
|
||||||
|
<symbol id="calendar-event" viewBox="0 0 16 16">
|
||||||
|
<path d="M11 6.5a.5.5 0 0 1 .5-.5h1a.5.5 0 0 1 .5.5v1a.5.5 0 0 1-.5.5h-1a.5.5 0 0 1-.5-.5v-1z"/>
|
||||||
|
<path d="M3.5 0a.5.5 0 0 1 .5.5V1h8V.5a.5.5 0 0 1 1 0V1h1a2 2 0 0 1 2 2v11a2 2 0 0 1-2 2H2a2 2 0 0 1-2-2V3a2 2 0 0 1 2-2h1V.5a.5.5 0 0 1 .5-.5zM1 4v10a1 1 0 0 0 1 1h12a1 1 0 0 0 1-1V4H1z"/>
|
||||||
|
</symbol>
|
||||||
|
|
||||||
|
<symbol id="alarm" viewBox="0 0 16 16">
|
||||||
|
<path d="M8.5 5.5a.5.5 0 0 0-1 0v3.362l-1.429 2.38a.5.5 0 1 0 .858.515l1.5-2.5A.5.5 0 0 0 8.5 9V5.5z"/>
|
||||||
|
<path d="M6.5 0a.5.5 0 0 0 0 1H7v1.07a7.001 7.001 0 0 0-3.273 12.474l-.602.602a.5.5 0 0 0 .707.708l.746-.746A6.97 6.97 0 0 0 8 16a6.97 6.97 0 0 0 3.422-.892l.746.746a.5.5 0 0 0 .707-.708l-.601-.602A7.001 7.001 0 0 0 9 2.07V1h.5a.5.5 0 0 0 0-1h-3zm1.038 3.018a6.093 6.093 0 0 1 .924 0 6 6 0 1 1-.924 0zM0 3.5c0 .753.333 1.429.86 1.887A8.035 8.035 0 0 1 4.387 1.86 2.5 2.5 0 0 0 0 3.5zM13.5 1c-.753 0-1.429.333-1.887.86a8.035 8.035 0 0 1 3.527 3.527A2.5 2.5 0 0 0 13.5 1z"/>
|
||||||
|
</symbol>
|
||||||
|
|
||||||
|
<symbol id="list-check" viewBox="0 0 16 16">
|
||||||
|
<path fill-rule="evenodd" d="M5 11.5a.5.5 0 0 1 .5-.5h9a.5.5 0 0 1 0 1h-9a.5.5 0 0 1-.5-.5zm0-4a.5.5 0 0 1 .5-.5h9a.5.5 0 0 1 0 1h-9a.5.5 0 0 1-.5-.5zm0-4a.5.5 0 0 1 .5-.5h9a.5.5 0 0 1 0 1h-9a.5.5 0 0 1-.5-.5zM3.854 2.146a.5.5 0 0 1 0 .708l-1.5 1.5a.5.5 0 0 1-.708 0l-.5-.5a.5.5 0 1 1 .708-.708L2 3.293l1.146-1.147a.5.5 0 0 1 .708 0zm0 4a.5.5 0 0 1 0 .708l-1.5 1.5a.5.5 0 0 1-.708 0l-.5-.5a.5.5 0 1 1 .708-.708L2 7.293l1.146-1.147a.5.5 0 0 1 .708 0zm0 4a.5.5 0 0 1 0 .708l-1.5 1.5a.5.5 0 0 1-.708 0l-.5-.5a.5.5 0 0 1 .708-.708l.146.147 1.146-1.147a.5.5 0 0 1 .708 0z"/>
|
||||||
|
</symbol>
|
||||||
|
</svg>
|
||||||
|
|
||||||
|
<div class="d-flex flex-column flex-md-row p-4 gap-4 py-md-5 align-items-center justify-content-center">
|
||||||
|
<div class="list-group">
|
||||||
|
<a href="#" class="list-group-item list-group-item-action d-flex gap-3 py-3" aria-current="true">
|
||||||
|
<img src="https://github.com/twbs.png" alt="twbs" width="32" height="32" class="rounded-circle flex-shrink-0">
|
||||||
|
<div class="d-flex gap-2 w-100 justify-content-between">
|
||||||
|
<div>
|
||||||
|
<h6 class="mb-0">List group item heading</h6>
|
||||||
|
<p class="mb-0 opacity-75">Some placeholder content in a paragraph.</p>
|
||||||
|
</div>
|
||||||
|
<small class="opacity-50 text-nowrap">now</small>
|
||||||
|
</div>
|
||||||
|
</a>
|
||||||
|
<a href="#" class="list-group-item list-group-item-action d-flex gap-3 py-3" aria-current="true">
|
||||||
|
<img src="https://github.com/twbs.png" alt="twbs" width="32" height="32" class="rounded-circle flex-shrink-0">
|
||||||
|
<div class="d-flex gap-2 w-100 justify-content-between">
|
||||||
|
<div>
|
||||||
|
<h6 class="mb-0">Another title here</h6>
|
||||||
|
<p class="mb-0 opacity-75">Some placeholder content in a paragraph that goes a little longer so it wraps to a new line.</p>
|
||||||
|
</div>
|
||||||
|
<small class="opacity-50 text-nowrap">3d</small>
|
||||||
|
</div>
|
||||||
|
</a>
|
||||||
|
<a href="#" class="list-group-item list-group-item-action d-flex gap-3 py-3" aria-current="true">
|
||||||
|
<img src="https://github.com/twbs.png" alt="twbs" width="32" height="32" class="rounded-circle flex-shrink-0">
|
||||||
|
<div class="d-flex gap-2 w-100 justify-content-between">
|
||||||
|
<div>
|
||||||
|
<h6 class="mb-0">Third heading</h6>
|
||||||
|
<p class="mb-0 opacity-75">Some placeholder content in a paragraph.</p>
|
||||||
|
</div>
|
||||||
|
<small class="opacity-50 text-nowrap">1w</small>
|
||||||
|
</div>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="b-example-divider"></div>
|
||||||
|
|
||||||
|
<div class="d-flex flex-column flex-md-row p-4 gap-4 py-md-5 align-items-center justify-content-center">
|
||||||
|
<div class="list-group">
|
||||||
|
<label class="list-group-item d-flex gap-2">
|
||||||
|
<input class="form-check-input flex-shrink-0" type="checkbox" value="" checked>
|
||||||
|
<span>
|
||||||
|
First checkbox
|
||||||
|
<small class="d-block text-body-secondary">With support text underneath to add more detail</small>
|
||||||
|
</span>
|
||||||
|
</label>
|
||||||
|
<label class="list-group-item d-flex gap-2">
|
||||||
|
<input class="form-check-input flex-shrink-0" type="checkbox" value="">
|
||||||
|
<span>
|
||||||
|
Second checkbox
|
||||||
|
<small class="d-block text-body-secondary">Some other text goes here</small>
|
||||||
|
</span>
|
||||||
|
</label>
|
||||||
|
<label class="list-group-item d-flex gap-2">
|
||||||
|
<input class="form-check-input flex-shrink-0" type="checkbox" value="">
|
||||||
|
<span>
|
||||||
|
Third checkbox
|
||||||
|
<small class="d-block text-body-secondary">And we end with another snippet of text</small>
|
||||||
|
</span>
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="list-group">
|
||||||
|
<label class="list-group-item d-flex gap-2">
|
||||||
|
<input class="form-check-input flex-shrink-0" type="radio" name="listGroupRadios" id="listGroupRadios1" value="" checked>
|
||||||
|
<span>
|
||||||
|
First radio
|
||||||
|
<small class="d-block text-body-secondary">With support text underneath to add more detail</small>
|
||||||
|
</span>
|
||||||
|
</label>
|
||||||
|
<label class="list-group-item d-flex gap-2">
|
||||||
|
<input class="form-check-input flex-shrink-0" type="radio" name="listGroupRadios" id="listGroupRadios2" value="">
|
||||||
|
<span>
|
||||||
|
Second radio
|
||||||
|
<small class="d-block text-body-secondary">Some other text goes here</small>
|
||||||
|
</span>
|
||||||
|
</label>
|
||||||
|
<label class="list-group-item d-flex gap-2">
|
||||||
|
<input class="form-check-input flex-shrink-0" type="radio" name="listGroupRadios" id="listGroupRadios3" value="">
|
||||||
|
<span>
|
||||||
|
Third radio
|
||||||
|
<small class="d-block text-body-secondary">And we end with another snippet of text</small>
|
||||||
|
</span>
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="b-example-divider"></div>
|
||||||
|
|
||||||
|
<div class="d-flex flex-column flex-md-row p-4 gap-4 py-md-5 align-items-center justify-content-center">
|
||||||
|
<div class="list-group">
|
||||||
|
<label class="list-group-item d-flex gap-3">
|
||||||
|
<input class="form-check-input flex-shrink-0" type="checkbox" value="" checked style="font-size: 1.375em;">
|
||||||
|
<span class="pt-1 form-checked-content">
|
||||||
|
<strong>Finish sales report</strong>
|
||||||
|
<small class="d-block text-body-secondary">
|
||||||
|
<svg class="bi me-1" width="1em" height="1em"><use xlink:href="#calendar-event"/></svg>
|
||||||
|
1:00–2:00pm
|
||||||
|
</small>
|
||||||
|
</span>
|
||||||
|
</label>
|
||||||
|
<label class="list-group-item d-flex gap-3">
|
||||||
|
<input class="form-check-input flex-shrink-0" type="checkbox" value="" style="font-size: 1.375em;">
|
||||||
|
<span class="pt-1 form-checked-content">
|
||||||
|
<strong>Weekly All Hands</strong>
|
||||||
|
<small class="d-block text-body-secondary">
|
||||||
|
<svg class="bi me-1" width="1em" height="1em"><use xlink:href="#calendar-event"/></svg>
|
||||||
|
2:00–2:30pm
|
||||||
|
</small>
|
||||||
|
</span>
|
||||||
|
</label>
|
||||||
|
<label class="list-group-item d-flex gap-3">
|
||||||
|
<input class="form-check-input flex-shrink-0" type="checkbox" value="" style="font-size: 1.375em;">
|
||||||
|
<span class="pt-1 form-checked-content">
|
||||||
|
<strong>Out of office</strong>
|
||||||
|
<small class="d-block text-body-secondary">
|
||||||
|
<svg class="bi me-1" width="1em" height="1em"><use xlink:href="#alarm"/></svg>
|
||||||
|
Tomorrow
|
||||||
|
</small>
|
||||||
|
</span>
|
||||||
|
</label>
|
||||||
|
<label class="list-group-item d-flex gap-3 bg-body-tertiary">
|
||||||
|
<input class="form-check-input form-check-input-placeholder bg-body-tertiary flex-shrink-0 pe-none" disabled type="checkbox" value="" style="font-size: 1.375em;">
|
||||||
|
<span class="pt-1 form-checked-content">
|
||||||
|
<span contenteditable="true" class="w-100">Add new task...</span>
|
||||||
|
<small class="d-block text-body-secondary">
|
||||||
|
<svg class="bi me-1" width="1em" height="1em"><use xlink:href="#list-check"/></svg>
|
||||||
|
Choose list...
|
||||||
|
</small>
|
||||||
|
</span>
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="b-example-divider"></div>
|
||||||
|
|
||||||
|
<div class="d-flex flex-column flex-md-row p-4 gap-4 py-md-5 align-items-center justify-content-center">
|
||||||
|
<div class="list-group list-group-checkable d-grid gap-2 border-0">
|
||||||
|
<input class="list-group-item-check pe-none" type="radio" name="listGroupCheckableRadios" id="listGroupCheckableRadios1" value="" checked>
|
||||||
|
<label class="list-group-item rounded-3 py-3" for="listGroupCheckableRadios1">
|
||||||
|
First radio
|
||||||
|
<span class="d-block small opacity-50">With support text underneath to add more detail</span>
|
||||||
|
</label>
|
||||||
|
|
||||||
|
<input class="list-group-item-check pe-none" type="radio" name="listGroupCheckableRadios" id="listGroupCheckableRadios2" value="">
|
||||||
|
<label class="list-group-item rounded-3 py-3" for="listGroupCheckableRadios2">
|
||||||
|
Second radio
|
||||||
|
<span class="d-block small opacity-50">Some other text goes here</span>
|
||||||
|
</label>
|
||||||
|
|
||||||
|
<input class="list-group-item-check pe-none" type="radio" name="listGroupCheckableRadios" id="listGroupCheckableRadios3" value="">
|
||||||
|
<label class="list-group-item rounded-3 py-3" for="listGroupCheckableRadios3">
|
||||||
|
Third radio
|
||||||
|
<span class="d-block small opacity-50">And we end with another snippet of text</span>
|
||||||
|
</label>
|
||||||
|
|
||||||
|
<input class="list-group-item-check pe-none" type="radio" name="listGroupCheckableRadios" id="listGroupCheckableRadios4" value="" disabled>
|
||||||
|
<label class="list-group-item rounded-3 py-3" for="listGroupCheckableRadios4">
|
||||||
|
Fourth disabled radio
|
||||||
|
<span class="d-block small opacity-50">This option is disabled</span>
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="b-example-divider"></div>
|
||||||
|
|
||||||
|
<div class="d-flex flex-column flex-md-row p-4 gap-4 py-md-5 align-items-center justify-content-center">
|
||||||
|
<div class="list-group list-group-radio d-grid gap-2 border-0">
|
||||||
|
<div class="position-relative">
|
||||||
|
<input class="form-check-input position-absolute top-50 end-0 me-3 fs-5" type="radio" name="listGroupRadioGrid" id="listGroupRadioGrid1" value="" checked>
|
||||||
|
<label class="list-group-item py-3 pe-5" for="listGroupRadioGrid1">
|
||||||
|
<strong class="fw-semibold">First radio</strong>
|
||||||
|
<span class="d-block small opacity-75">With support text underneath to add more detail</span>
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="position-relative">
|
||||||
|
<input class="form-check-input position-absolute top-50 end-0 me-3 fs-5" type="radio" name="listGroupRadioGrid" id="listGroupRadioGrid2" value="">
|
||||||
|
<label class="list-group-item py-3 pe-5" for="listGroupRadioGrid2">
|
||||||
|
<strong class="fw-semibold">Second radio</strong>
|
||||||
|
<span class="d-block small opacity-75">Some other text goes here</span>
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="position-relative">
|
||||||
|
<input class="form-check-input position-absolute top-50 end-0 me-3 fs-5" type="radio" name="listGroupRadioGrid" id="listGroupRadioGrid3" value="">
|
||||||
|
<label class="list-group-item py-3 pe-5" for="listGroupRadioGrid3">
|
||||||
|
<strong class="fw-semibold">Third radio</strong>
|
||||||
|
<span class="d-block small opacity-75">And we end with another snippet of text</span>
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="position-relative">
|
||||||
|
<input class="form-check-input position-absolute top-50 end-0 me-3 fs-5" type="radio" name="listGroupRadioGrid" id="listGroupRadioGrid4" value="" disabled>
|
||||||
|
<label class="list-group-item py-3 pe-5" for="listGroupRadioGrid4">
|
||||||
|
<strong class="fw-semibold">Fourth disabled radio</strong>
|
||||||
|
<span class="d-block small opacity-75">This option is disabled</span>
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<script src="https://getbootstrap.com/docs/5.3/dist/js/bootstrap.bundle.min.js" integrity="sha384-YvpcrYf0tY3lHB60NNkmXc5s9fDVZLESaAA55NDzOxhy9GkcIdslK1eN7N6jIeHz" crossorigin="anonymous"></script>
|
||||||
|
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
86
polls/templates/polls/detail.html
Normal file
86
polls/templates/polls/detail.html
Normal file
@ -0,0 +1,86 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en" data-bs-theme="dark">
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
|
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-QWTKZyjpPEjISv5WaRU9OFeRpok6YctnYmDr5pNlyT2bRjXh0JMhjY6hW+ALEwIH" crossorigin="anonymous">
|
||||||
|
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/js/bootstrap.bundle.min.js" integrity="sha384-YvpcrYf0tY3lHB60NNkmXc5s9fDVZLESaAA55NDzOxhy9GkcIdslK1eN7N6jIeHz" crossorigin="anonymous"></script>
|
||||||
|
<title>Testapp</title>
|
||||||
|
<style>
|
||||||
|
.darker-bg {
|
||||||
|
background-color: #171a1e;
|
||||||
|
}
|
||||||
|
.list-group {
|
||||||
|
width: 100%;
|
||||||
|
max-width: 460px;
|
||||||
|
margin-inline: 1.5rem;
|
||||||
|
}
|
||||||
|
.list-group-checkable .list-group-item {
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
.list-group-item-check {
|
||||||
|
position: absolute;
|
||||||
|
clip: rect(0, 0, 0, 0);
|
||||||
|
}
|
||||||
|
.list-group-item-check:hover + .list-group-item {
|
||||||
|
background-color: var(--bs-secondary-bg);
|
||||||
|
}
|
||||||
|
.list-group-item-check:checked + .list-group-item {
|
||||||
|
color: #fff;
|
||||||
|
background-color: var(--bs-primary);
|
||||||
|
border-color: var(--bs-primary);
|
||||||
|
}
|
||||||
|
.list-group-item-check[disabled] + .list-group-item,
|
||||||
|
.list-group-item-check:disabled + .list-group-item {
|
||||||
|
pointer-events: none;
|
||||||
|
filter: none;
|
||||||
|
opacity: .5;
|
||||||
|
}
|
||||||
|
.list-group-radio .list-group-item {
|
||||||
|
cursor: pointer;
|
||||||
|
border-radius: .5rem;
|
||||||
|
}
|
||||||
|
.list-group-radio .form-check-input {
|
||||||
|
z-index: 2;
|
||||||
|
margin-top: -.5em;
|
||||||
|
}
|
||||||
|
.list-group-radio .list-group-item:hover,
|
||||||
|
.list-group-radio .list-group-item:focus {
|
||||||
|
background-color: var(--bs-secondary-bg);
|
||||||
|
}
|
||||||
|
|
||||||
|
.list-group-radio .form-check-input:checked + .list-group-item {
|
||||||
|
background-color: var(--bs-body);
|
||||||
|
border-color: var(--bs-primary);
|
||||||
|
box-shadow: 0 0 0 2px var(--bs-primary);
|
||||||
|
}
|
||||||
|
.list-group-radio .form-check-input[disabled] + .list-group-item,
|
||||||
|
.list-group-radio .form-check-input:disabled + .list-group-item {
|
||||||
|
pointer-events: none;
|
||||||
|
filter: none;
|
||||||
|
opacity: .5;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div class="px-4 py-5 my-5 text-center shadow darker-bg">
|
||||||
|
<h1 class="display-5 fw-bold text-body-emphasis">{{ question.question_text }}</h1>
|
||||||
|
<br/>
|
||||||
|
|
||||||
|
<form action="{% url 'polls:vote' question.id %}" method="post">
|
||||||
|
{% csrf_token %}
|
||||||
|
<fieldset class="d-flex flex-column flex-md-row col-lg-6 mx-auto align-items-center justify-content-center">
|
||||||
|
{% if error_message %}<p><strong>{{ error_message }}</strong></p>{% endif %}
|
||||||
|
<div class="list-group list-group-checkable d-grid gap-2 border-0">
|
||||||
|
{% for choice in question.choice_set.all %}
|
||||||
|
<input class="list-group-item-check pe-none" type="radio" name="choice" id="choice{{ forloop.counter }}" value="{{ choice.id }}">
|
||||||
|
<label class="list-group-item rounded-3 py-3" for="choice{{ forloop.counter }}">{{ choice.choice_text }}</label><br>
|
||||||
|
{% endfor %}
|
||||||
|
</div>
|
||||||
|
</fieldset>
|
||||||
|
<br/>
|
||||||
|
<input class="btn btn-success rounded-3 px-3" type="submit" value="Vote">
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
45
polls/templates/polls/index.html
Normal file
45
polls/templates/polls/index.html
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en" data-bs-theme="dark">
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
|
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-QWTKZyjpPEjISv5WaRU9OFeRpok6YctnYmDr5pNlyT2bRjXh0JMhjY6hW+ALEwIH" crossorigin="anonymous">
|
||||||
|
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/js/bootstrap.bundle.min.js" integrity="sha384-YvpcrYf0tY3lHB60NNkmXc5s9fDVZLESaAA55NDzOxhy9GkcIdslK1eN7N6jIeHz" crossorigin="anonymous"></script>
|
||||||
|
<title>Testapp</title>
|
||||||
|
<style>
|
||||||
|
.darker-bg {
|
||||||
|
background-color: #171a1e;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div class="px-4 py-5 my-5 shadow darker-bg">
|
||||||
|
<h1 class="display-5 fw-bold text-body-emphasis text-center">Polls</h1>
|
||||||
|
<br/>
|
||||||
|
<div class="d-flex flex-column flex-md-row col-lg-6 mx-auto align-items-center justify-content-center">
|
||||||
|
{% if latest_question_list %}
|
||||||
|
<div class="list-group">
|
||||||
|
{% for question in latest_question_list %}
|
||||||
|
<a href="{% url 'polls:detail' question.id %}" class="list-group-item list-group-item-action d-flex gap-3 py-3" aria-current="true">
|
||||||
|
<!--<img src="https://github.com/twbs.png" alt="twbs" width="32" height="32" class="rounded-circle flex-shrink-0"> -->
|
||||||
|
<div class="d-flex gap-2 w-100 justify-content-between">
|
||||||
|
<div>
|
||||||
|
<h6 class="mb-0">{{ question.question_text }}</h6>
|
||||||
|
<!-- <p class="mb-0 opacity-75">Some placeholder content in a paragraph.</p> -->
|
||||||
|
</div>
|
||||||
|
<small class="opacity-50 text-nowrap">{{ question.pub_date }}</small>
|
||||||
|
</div>
|
||||||
|
</a>
|
||||||
|
{% endfor %}
|
||||||
|
</div>
|
||||||
|
{% else %}
|
||||||
|
<p class="text-center text-muted">
|
||||||
|
No polls are available.<br />
|
||||||
|
You can create polls in the <a href="/admin/polls/question/">admin panel</a>
|
||||||
|
</p>
|
||||||
|
{% endif %}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
94
polls/templates/polls/listform.html
Normal file
94
polls/templates/polls/listform.html
Normal file
@ -0,0 +1,94 @@
|
|||||||
|
<!doctype html>
|
||||||
|
<html lang="en" data-bs-theme="dark">
|
||||||
|
<head>
|
||||||
|
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
|
<meta name="description" content="">
|
||||||
|
<meta name="author" content="Mark Otto, Jacob Thornton, and Bootstrap contributors">
|
||||||
|
<meta name="generator" content="Hugo 0.122.0">
|
||||||
|
<title>List groups · Bootstrap v5.3</title>
|
||||||
|
|
||||||
|
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-QWTKZyjpPEjISv5WaRU9OFeRpok6YctnYmDr5pNlyT2bRjXh0JMhjY6hW+ALEwIH" crossorigin="anonymous">
|
||||||
|
<!-- Custom styles for this template -->
|
||||||
|
<!--<link href="list-groups.css" rel="stylesheet">-->
|
||||||
|
<style>
|
||||||
|
.list-group {
|
||||||
|
width: 100%;
|
||||||
|
max-width: 460px;
|
||||||
|
margin-inline: 1.5rem;
|
||||||
|
}
|
||||||
|
.list-group-checkable .list-group-item {
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
.list-group-item-check {
|
||||||
|
position: absolute;
|
||||||
|
clip: rect(0, 0, 0, 0);
|
||||||
|
}
|
||||||
|
.list-group-item-check:hover + .list-group-item {
|
||||||
|
background-color: var(--bs-secondary-bg);
|
||||||
|
}
|
||||||
|
.list-group-item-check:checked + .list-group-item {
|
||||||
|
color: #fff;
|
||||||
|
background-color: var(--bs-primary);
|
||||||
|
border-color: var(--bs-primary);
|
||||||
|
}
|
||||||
|
.list-group-item-check[disabled] + .list-group-item,
|
||||||
|
.list-group-item-check:disabled + .list-group-item {
|
||||||
|
pointer-events: none;
|
||||||
|
filter: none;
|
||||||
|
opacity: .5;
|
||||||
|
}
|
||||||
|
.list-group-radio .list-group-item {
|
||||||
|
cursor: pointer;
|
||||||
|
border-radius: .5rem;
|
||||||
|
}
|
||||||
|
.list-group-radio .form-check-input {
|
||||||
|
z-index: 2;
|
||||||
|
margin-top: -.5em;
|
||||||
|
}
|
||||||
|
.list-group-radio .list-group-item:hover,
|
||||||
|
.list-group-radio .list-group-item:focus {
|
||||||
|
background-color: var(--bs-secondary-bg);
|
||||||
|
}
|
||||||
|
|
||||||
|
.list-group-radio .form-check-input:checked + .list-group-item {
|
||||||
|
background-color: var(--bs-body);
|
||||||
|
border-color: var(--bs-primary);
|
||||||
|
box-shadow: 0 0 0 2px var(--bs-primary);
|
||||||
|
}
|
||||||
|
.list-group-radio .form-check-input[disabled] + .list-group-item,
|
||||||
|
.list-group-radio .form-check-input:disabled + .list-group-item {
|
||||||
|
pointer-events: none;
|
||||||
|
filter: none;
|
||||||
|
opacity: .5;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div class="d-flex flex-column flex-md-row p-4 gap-4 py-md-5 align-items-center justify-content-center">
|
||||||
|
<div class="list-group list-group-checkable d-grid gap-2 border-0">
|
||||||
|
<input class="list-group-item-check pe-none" type="radio" name="listGroupCheckableRadios" id="listGroupCheckableRadios1" value="" checked>
|
||||||
|
<label class="list-group-item rounded-3 py-3" for="listGroupCheckableRadios1">
|
||||||
|
First radio
|
||||||
|
</label>
|
||||||
|
|
||||||
|
<input class="list-group-item-check pe-none" type="radio" name="listGroupCheckableRadios" id="listGroupCheckableRadios2" value="">
|
||||||
|
<label class="list-group-item rounded-3 py-3" for="listGroupCheckableRadios2">
|
||||||
|
Second radio
|
||||||
|
</label>
|
||||||
|
|
||||||
|
<input class="list-group-item-check pe-none" type="radio" name="listGroupCheckableRadios" id="listGroupCheckableRadios3" value="">
|
||||||
|
<label class="list-group-item rounded-3 py-3" for="listGroupCheckableRadios3">
|
||||||
|
Third radio
|
||||||
|
</label>
|
||||||
|
|
||||||
|
<input class="list-group-item-check pe-none" type="radio" name="listGroupCheckableRadios" id="listGroupCheckableRadios4" value="" disabled>
|
||||||
|
<label class="list-group-item rounded-3 py-3" for="listGroupCheckableRadios4">
|
||||||
|
Fourth disabled radio
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
92
polls/templates/polls/results.html
Normal file
92
polls/templates/polls/results.html
Normal file
@ -0,0 +1,92 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en" data-bs-theme="dark">
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
|
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-QWTKZyjpPEjISv5WaRU9OFeRpok6YctnYmDr5pNlyT2bRjXh0JMhjY6hW+ALEwIH" crossorigin="anonymous">
|
||||||
|
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/js/bootstrap.bundle.min.js" integrity="sha384-YvpcrYf0tY3lHB60NNkmXc5s9fDVZLESaAA55NDzOxhy9GkcIdslK1eN7N6jIeHz" crossorigin="anonymous"></script>
|
||||||
|
<title>Testapp</title>
|
||||||
|
<style>
|
||||||
|
.darker-bg {
|
||||||
|
background-color: #171a1e;
|
||||||
|
}
|
||||||
|
.list-group {
|
||||||
|
width: 100%;
|
||||||
|
max-width: 460px;
|
||||||
|
margin-inline: 1.5rem;
|
||||||
|
}
|
||||||
|
.list-group-checkable .list-group-item {
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
.list-group-item-check {
|
||||||
|
position: absolute;
|
||||||
|
clip: rect(0, 0, 0, 0);
|
||||||
|
}
|
||||||
|
.list-group-item-check:hover + .list-group-item {
|
||||||
|
background-color: var(--bs-secondary-bg);
|
||||||
|
}
|
||||||
|
.list-group-item-check:checked + .list-group-item {
|
||||||
|
color: #fff;
|
||||||
|
background-color: var(--bs-primary);
|
||||||
|
border-color: var(--bs-primary);
|
||||||
|
}
|
||||||
|
.list-group-item-check[disabled] + .list-group-item,
|
||||||
|
.list-group-item-check:disabled + .list-group-item {
|
||||||
|
pointer-events: none;
|
||||||
|
filter: none;
|
||||||
|
opacity: .5;
|
||||||
|
}
|
||||||
|
.list-group-radio .list-group-item {
|
||||||
|
cursor: pointer;
|
||||||
|
border-radius: .5rem;
|
||||||
|
}
|
||||||
|
.list-group-radio .form-check-input {
|
||||||
|
z-index: 2;
|
||||||
|
margin-top: -.5em;
|
||||||
|
}
|
||||||
|
.list-group-radio .list-group-item:hover,
|
||||||
|
.list-group-radio .list-group-item:focus {
|
||||||
|
background-color: var(--bs-secondary-bg);
|
||||||
|
}
|
||||||
|
|
||||||
|
.list-group-radio .form-check-input:checked + .list-group-item {
|
||||||
|
background-color: var(--bs-body);
|
||||||
|
border-color: var(--bs-primary);
|
||||||
|
box-shadow: 0 0 0 2px var(--bs-primary);
|
||||||
|
}
|
||||||
|
.list-group-radio .form-check-input[disabled] + .list-group-item,
|
||||||
|
.list-group-radio .form-check-input:disabled + .list-group-item {
|
||||||
|
pointer-events: none;
|
||||||
|
filter: none;
|
||||||
|
opacity: .5;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div class="px-4 py-5 my-5 shadow darker-bg">
|
||||||
|
<h1 class="display-5 fw-bold text-body-emphasis text-center">{{ question.question_text }}</h1>
|
||||||
|
<br/>
|
||||||
|
<h1 class="text-center">Results</h1>
|
||||||
|
<div class="d-flex flex-column flex-md-row col-lg-6 mx-auto align-items-center justify-content-center">
|
||||||
|
<div class="list-group">
|
||||||
|
{% for choice_text, choice_votes, choice_percent in choices %}
|
||||||
|
<div class="list-group-item list-group-item-action d-flex gap-3 py-3">
|
||||||
|
<div class="d-flex gap-2 w-100 justify-content-between">
|
||||||
|
<div>
|
||||||
|
<h6 class="mb-0">{{ choice_text }}</h6>
|
||||||
|
<!--
|
||||||
|
<div role="progressbar" aria-label="{{ choice_text }}" aria-valuenow="{{ choice_percent }}" aria-valuemin="0" aria-valuemax="100" class="progress">
|
||||||
|
<div class="progress-bar" style="width: {{ choice_percent }}%"></div>
|
||||||
|
</div>
|
||||||
|
-->
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<small class="text-nowrap">{{ choice_votes }} vote{{ choice_votes|pluralize }}</small>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{% endfor %}
|
||||||
|
</div{{ question.question_text }}>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
3
polls/tests.py
Normal file
3
polls/tests.py
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
from django.test import TestCase
|
||||||
|
|
||||||
|
# Create your tests here.
|
||||||
15
polls/urls.py
Normal file
15
polls/urls.py
Normal file
@ -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("<int:question_id>/", views.detail, name="detail"),
|
||||||
|
# ex: /polls/5/results/
|
||||||
|
path("<int:question_id>/results/", views.results, name="results"),
|
||||||
|
# ex: /polls/5/vote/
|
||||||
|
path("<int:question_id>/vote/", views.vote, name="vote"),
|
||||||
|
]
|
||||||
41
polls/views.py
Normal file
41
polls/views.py
Normal file
@ -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,)))
|
||||||
Loading…
x
Reference in New Issue
Block a user