Repository: devmahmud/Django-Poll-App
Branch: master
Commit: 695964d77899
Files: 44
Total size: 53.7 KB
Directory structure:
gitextract_nnisl5fi/
├── .gitignore
├── LICENSE
├── README.md
├── accounts/
│ ├── __init__.py
│ ├── admin.py
│ ├── apps.py
│ ├── forms.py
│ ├── migrations/
│ │ └── __init__.py
│ ├── models.py
│ ├── templates/
│ │ └── accounts/
│ │ ├── login.html
│ │ └── register.html
│ ├── tests.py
│ ├── urls.py
│ └── views.py
├── manage.py
├── pollme/
│ ├── __init__.py
│ ├── settings.py
│ ├── urls.py
│ ├── views.py
│ └── wsgi.py
├── polls/
│ ├── __init__.py
│ ├── admin.py
│ ├── apps.py
│ ├── forms.py
│ ├── migrations/
│ │ ├── 0001_initial.py
│ │ ├── 0002_auto_20231018_1318.py
│ │ └── __init__.py
│ ├── models.py
│ ├── templates/
│ │ └── polls/
│ │ ├── add_choice.html
│ │ ├── add_poll.html
│ │ ├── endpoll.html
│ │ ├── poll_detail.html
│ │ ├── poll_edit.html
│ │ ├── poll_result.html
│ │ └── polls_list.html
│ ├── tests.py
│ ├── urls.py
│ └── views.py
├── requirements.txt
├── seeder.py
├── static/
│ └── css/
│ └── home_style.css
└── templates/
├── base.html
├── home.html
└── includes/
└── navbar.html
================================================
FILE CONTENTS
================================================
================================================
FILE: .gitignore
================================================
*.log
*.pot
*.pyc
__pycache__/
local_settings.py
db.sqlite3
media
venv
.vscode
================================================
FILE: LICENSE
================================================
MIT License
Copyright (c) 2019 Mahmudul Alam
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
================================================
FILE: README.md
================================================
# Django-Poll-App
Django poll app is a full featured polling app. You have to register in this app to show the polls and to vote. If you already voted you can not vote again. Only the owner of a poll can add poll , edit poll, update poll, delete poll , add choice, update choice, delete choice and end a poll. If a poll is ended it can not be voted. Ended poll only shows user the final result of the poll. There is a search option for polls. Also user can filter polls by name, publish date, and by number of voted. Pagination will work even after applying filter.
<h1>Getting Started</h1>
<p>These instructions will get you a copy of the project up and running on your local machine for development and testing purposes.</p>
<h2>Prerequisites</h2>
<code>python== 3.5 or up and django==2.0 or up</code>
<h2>Installing</h2>
<pre>open terminal and type</pre>
<code>git clone https://github.com/devmahmud/Django-poll-app.git</code><br><br>
<h4>or simply download using the url below</h4>
<code>https://github.com/devmahmud/Django-poll-app.git</code><br>
<h2>To migrate the database open terminal in project directory and type</h2>
<code>python manage.py makemigrations</code><br>
<code>python manage.py migrate</code>
<h2>To use admin panel you need to create superuser using this command </h2>
<code>python manage.py createsuperuser</code>
<h2>To Create some dummy text data for your app follow the step below:</h2>
<code>pip install faker</code>
<code>python manage.py shell</code>
<code>import seeder</code>
<code>seeder.seed_all(30)</code>
<p>Here 30 is a number of entry. You can use it as your own</p>
<h2> To run the program in local server use the following command </h2>
<code>python manage.py runserver</code>
<p>Then go to http://127.0.0.1:8000 in your browser</p>
<h2>Project snapshot</h2>
<h3>Home page</h3>
<div align="center">
<img src="https://user-images.githubusercontent.com/19981097/51409444-0e40a600-1b8c-11e9-9ab0-27d759db8973.jpg" width="100%"</img>
</div>
<h3>Login Page</h3>
<div align="center">
<img src="https://user-images.githubusercontent.com/19981097/51409509-36c8a000-1b8c-11e9-845a-65b49262aa53.png" width="100%"</img>
</div>
<h3>Registration Page</h3>
<div align="center">
<img src="https://user-images.githubusercontent.com/19981097/51409562-5cee4000-1b8c-11e9-82f6-1aa2df159528.png" width="100%"</img>
</div>
<h3>Poll List Page</h3>
<div align="center">
<img src="https://user-images.githubusercontent.com/19981097/51409728-d423d400-1b8c-11e9-8903-4c08ba64512e.png" width="100%"</img>
</div>
<h3>Poll Add Page</h3>
<div align="center">
<img src="https://user-images.githubusercontent.com/19981097/51409796-fe759180-1b8c-11e9-941b-c1202956cca4.png" width="100%"</img>
</div>
<h3>Polling page</h3>
<div align="center">
<img src="https://user-images.githubusercontent.com/19981097/51409843-1e0cba00-1b8d-11e9-9109-cceb79a6a623.png" width="100%"</img>
</div>
<h3>Poll Result Page</h3>
<div align="center">
<img src="https://user-images.githubusercontent.com/19981097/51409932-60ce9200-1b8d-11e9-9c83-c59ba498ca8b.png" width="100%"</img>
</div>
<h3>Poll Edit Page</h3>
<div align="center">
<img src="https://user-images.githubusercontent.com/19981097/51410008-92dff400-1b8d-11e9-8172-c228e4b60e28.png" width="100%"</img>
</div>
<h3>Choice Update Delete Page</h3>
<div align="center">
<img src="https://user-images.githubusercontent.com/19981097/51410442-dc7d0e80-1b8e-11e9-8f8e-18e6d7bb70fb.png" width="100%"</img>
</div>
<h2>Author</h2>
<blockquote>
Mahmudul alam<br>
Email: expelmahmud@gmail.com
</blockquote>
<div align="center">
<h3>========Thank You !!!=========</h3>
</div>
================================================
FILE: accounts/__init__.py
================================================
================================================
FILE: accounts/admin.py
================================================
from django.contrib import admin
# Register your models here.
================================================
FILE: accounts/apps.py
================================================
from django.apps import AppConfig
class AccountsConfig(AppConfig):
name = 'accounts'
================================================
FILE: accounts/forms.py
================================================
from django import forms
from django.contrib.auth.models import User
class UserRegistrationForm(forms.Form):
username = forms.CharField(label='Username', max_length=100, min_length=5,
widget=forms.TextInput(attrs={'class': 'form-control'}))
email = forms.EmailField(label='Email', max_length=35, min_length=5,
widget=forms.EmailInput(attrs={'class': 'form-control'}))
password1 = forms.CharField(label='Password', max_length=50, min_length=5,
widget=forms.PasswordInput(attrs={'class': 'form-control'}))
password2 = forms.CharField(label='Confirm Password',
max_length=50, min_length=5,
widget=forms.PasswordInput(attrs={'class': 'form-control'}))
================================================
FILE: accounts/migrations/__init__.py
================================================
================================================
FILE: accounts/models.py
================================================
from django.db import models
# Create your models here.
================================================
FILE: accounts/templates/accounts/login.html
================================================
{% extends 'base.html' %}
{% block content %}
<div class="vh-100 d-flex justify-content-center align-items-center p-5" id="login-content">
<div class="col-md-5 p-5 shadow-sm border rounded-5 border-primary bg-white">
<h2 class="text-center mb-4 text-primary">Login</h2>
{% 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">×</span>
</button>
</div>
{% endfor %}
</div>
{% endif %}
<form action="" method="post">
{% csrf_token %}
<div class="mb-3">
<label for="username" class="form-label">Username</label>
<input type="text" class="form-control border border-primary" id="username"
aria-describedby="username" name="username" placeholder="Enter Username" required>
</div>
<div class="mb-3">
<label for="password" class="form-label">Password</label>
<input type="password" class="form-control border border-primary" name="password"
placeholder="Password" required>
</div>
<div class="d-grid">
<button class="btn btn-primary" type="submit">Login</button>
</div>
</form>
<div class="mt-3">
<p class="mb-0 text-center">Don't have an account? <a href="{% url 'accounts:register' %}"
class="text-primary fw-bold">Sign
Up</a></p>
</div>
</div>
</div>
{% endblock %}
================================================
FILE: accounts/templates/accounts/register.html
================================================
{% extends 'base.html' %}
{% block content %}
<div class="container">
<div class="row center">
<div class="col-md-5 mx-auto p-5 shadow-sm border rounded border-primary">
<p>Already have an account? <a href="{% url 'accounts:login' %}">Login Here</a></p>
{% 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">×</span>
</button>
</div>
{% endfor %}
</div>
{% endif %}
<form action="" method="POST">
{% csrf_token %}
{{ form.as_p }}
<button type="submit" class="btn btn-primary">Sign Up</button>
</form>
</div>
</div>
</div>
{% endblock %}
================================================
FILE: accounts/tests.py
================================================
from django.test import TestCase
# Create your tests here.
================================================
FILE: accounts/urls.py
================================================
from django.urls import path
from . import views
app_name = "accounts"
urlpatterns=[
path('login/', views.login_user, name='login'),
path('logout/', views.logout_user, name='logout'),
path('register/', views.create_user, name='register'),
]
================================================
FILE: accounts/views.py
================================================
from django.contrib.auth import authenticate, login, logout
from django.shortcuts import render, redirect
from django.contrib.auth.models import User
from .forms import UserRegistrationForm
from django.contrib import messages
from django.http import HttpResponse
def login_user(request):
if request.method == 'POST':
username = request.POST.get('username')
password = request.POST.get('password')
user = authenticate(username=username, password=password)
if user is not None:
login(request, user)
redirect_url = request.GET.get('next', 'home')
return redirect(redirect_url)
else:
messages.error(request, "Username Or Password is incorrect!",
extra_tags='alert alert-warning alert-dismissible fade show')
return render(request, 'accounts/login.html')
def logout_user(request):
logout(request)
return redirect('home')
def create_user(request):
if request.method == 'POST':
check1 = False
check2 = False
check3 = False
form = UserRegistrationForm(request.POST)
if form.is_valid():
username = form.cleaned_data['username']
password1 = form.cleaned_data['password1']
password2 = form.cleaned_data['password2']
email = form.cleaned_data['email']
if password1 != password2:
check1 = True
messages.error(request, 'Password did not match!',
extra_tags='alert alert-warning alert-dismissible fade show')
if User.objects.filter(username=username).exists():
check2 = True
messages.error(request, 'Username already exists!',
extra_tags='alert alert-warning alert-dismissible fade show')
if User.objects.filter(email=email).exists():
check3 = True
messages.error(request, 'Email already registered!',
extra_tags='alert alert-warning alert-dismissible fade show')
if check1 or check2 or check3:
messages.error(
request, "Registration Failed!", extra_tags='alert alert-warning alert-dismissible fade show')
return redirect('accounts:register')
else:
user = User.objects.create_user(
username=username, password=password1, email=email)
messages.success(
request, f'Thanks for registering {user.username}.', extra_tags='alert alert-success alert-dismissible fade show')
return redirect('accounts:login')
else:
form = UserRegistrationForm()
return render(request, 'accounts/register.html', {'form': form})
================================================
FILE: manage.py
================================================
#!/usr/bin/env python
import os
import sys
if __name__ == '__main__':
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'pollme.settings')
try:
from django.core.management import execute_from_command_line
except ImportError as exc:
raise ImportError(
"Couldn't import Django. Are you sure it's installed and "
"available on your PYTHONPATH environment variable? Did you "
"forget to activate a virtual environment?"
) from exc
execute_from_command_line(sys.argv)
================================================
FILE: pollme/__init__.py
================================================
================================================
FILE: pollme/settings.py
================================================
"""
Django settings for pollme project.
Generated by 'django-admin startproject' using Django 2.1.5.
For more information on this file, see
https://docs.djangoproject.com/en/2.1/topics/settings/
For the full list of settings and their values, see
https://docs.djangoproject.com/en/2.1/ref/settings/
"""
import os
# Build paths inside the project like this: os.path.join(BASE_DIR, ...)
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
# Quick-start development settings - unsuitable for production
# See https://docs.djangoproject.com/en/2.1/howto/deployment/checklist/
# SECURITY WARNING: keep the secret key used in production secret!
SECRET_KEY = "x*za6xf&_80ofdpae!yzq61g9ffikkx9$*iygbl$j7rr4wlf8t"
# SECURITY WARNING: don't run with debug turned on in production!
DEBUG = True
ALLOWED_HOSTS = []
# Application definition
INSTALLED_APPS = [
"django.contrib.admin",
"django.contrib.auth",
"django.contrib.contenttypes",
"django.contrib.sessions",
"django.contrib.messages",
"django.contrib.staticfiles",
"polls.apps.PollsConfig",
"accounts.apps.AccountsConfig",
]
MIDDLEWARE = [
"django.middleware.security.SecurityMiddleware",
"django.contrib.sessions.middleware.SessionMiddleware",
"django.middleware.common.CommonMiddleware",
"django.middleware.csrf.CsrfViewMiddleware",
"django.contrib.auth.middleware.AuthenticationMiddleware",
"django.contrib.messages.middleware.MessageMiddleware",
"django.middleware.clickjacking.XFrameOptionsMiddleware",
]
ROOT_URLCONF = "pollme.urls"
TEMPLATES = [
{
"BACKEND": "django.template.backends.django.DjangoTemplates",
"DIRS": [os.path.join(BASE_DIR, "templates")],
"APP_DIRS": True,
"OPTIONS": {
"context_processors": [
"django.template.context_processors.debug",
"django.template.context_processors.request",
"django.contrib.auth.context_processors.auth",
"django.contrib.messages.context_processors.messages",
],
},
},
]
WSGI_APPLICATION = "pollme.wsgi.application"
# Database
# https://docs.djangoproject.com/en/2.1/ref/settings/#databases
DATABASES = {
"default": {
"ENGINE": "django.db.backends.sqlite3",
"NAME": os.path.join(BASE_DIR, "db.sqlite3"),
}
}
# Password validation
# https://docs.djangoproject.com/en/2.1/ref/settings/#auth-password-validators
AUTH_PASSWORD_VALIDATORS = [
{
"NAME": "django.contrib.auth.password_validation.UserAttributeSimilarityValidator",
},
{
"NAME": "django.contrib.auth.password_validation.MinimumLengthValidator",
},
{
"NAME": "django.contrib.auth.password_validation.CommonPasswordValidator",
},
{
"NAME": "django.contrib.auth.password_validation.NumericPasswordValidator",
},
]
# Internationalization
# https://docs.djangoproject.com/en/2.1/topics/i18n/
LANGUAGE_CODE = "en-us"
TIME_ZONE = "Asia/Dhaka"
USE_I18N = True
USE_L10N = True
USE_TZ = True
# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/2.1/howto/static-files/
STATIC_URL = "/static/"
STATICFILES_DIRS = [os.path.join(BASE_DIR, "static")]
DEFAULT_AUTO_FIELD = "django.db.models.AutoField"
================================================
FILE: pollme/urls.py
================================================
"""pollme URL Configuration
The `urlpatterns` list routes URLs to views. For more information please see:
https://docs.djangoproject.com/en/2.1/topics/http/urls/
Examples:
Function views
1. Add an import: from my_app import views
2. Add a URL to urlpatterns: path('', views.home, name='home')
Class-based views
1. Add an import: from other_app.views import Home
2. Add a URL to urlpatterns: path('', Home.as_view(), name='home')
Including another URLconf
1. Import the include() function: from django.urls import include, path
2. Add a URL to urlpatterns: path('blog/', include('blog.urls'))
"""
from django.contrib import admin
from django.urls import path, include
from . import views
urlpatterns = [
path('', views.home, name='home'),
path('admin/', admin.site.urls),
path('accounts/', include('accounts.urls', namespace="accounts")),
path('polls/', include('polls.urls', namespace="polls")),
]
================================================
FILE: pollme/views.py
================================================
from django.shortcuts import render
def home(request):
return render(request,'home.html')
================================================
FILE: pollme/wsgi.py
================================================
"""
WSGI config for pollme project.
It exposes the WSGI callable as a module-level variable named ``application``.
For more information on this file, see
https://docs.djangoproject.com/en/2.1/howto/deployment/wsgi/
"""
import os
from django.core.wsgi import get_wsgi_application
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'pollme.settings')
application = get_wsgi_application()
================================================
FILE: polls/__init__.py
================================================
================================================
FILE: polls/admin.py
================================================
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"]
================================================
FILE: polls/apps.py
================================================
from django.apps import AppConfig
class PollsConfig(AppConfig):
name = 'polls'
================================================
FILE: polls/forms.py
================================================
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', })
}
================================================
FILE: polls/migrations/0001_initial.py
================================================
# 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'),
),
]
================================================
FILE: polls/migrations/0002_auto_20231018_1318.py
================================================
# 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),
),
]
================================================
FILE: polls/migrations/__init__.py
================================================
================================================
FILE: polls/models.py
================================================
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}'
================================================
FILE: polls/templates/polls/add_choice.html
================================================
{% 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 %}
================================================
FILE: polls/templates/polls/add_poll.html
================================================
{% 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 %}
================================================
FILE: polls/templates/polls/endpoll.html
================================================
{% 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">×</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 %}
================================================
FILE: polls/templates/polls/poll_detail.html
================================================
{% 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">×</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 %}
================================================
FILE: polls/templates/polls/poll_edit.html
================================================
{% 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">×</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> 
{{ choice.choice_text }}</li>
{% endfor %}
</ul>
</div>
</div>
</div>
</div>
{% endblock %}
================================================
FILE: polls/templates/polls/poll_result.html
================================================
{% 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">×</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 %}
================================================
FILE: polls/templates/polls/polls_list.html
================================================
{% 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">×</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 %}
================================================
FILE: polls/tests.py
================================================
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'))
================================================
FILE: polls/urls.py
================================================
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'),
]
================================================
FILE: polls/views.py
================================================
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})
================================================
FILE: requirements.txt
================================================
asgiref==3.3.1
"Django>=4.2,<4.3"
pytz==2020.5
sqlparse==0.4.4
================================================
FILE: seeder.py
================================================
from polls.models import Choice, Poll, Vote
from django.contrib.auth.models import User
import datetime
import random
import time
from faker import Faker
fake = Faker()
def seed_users(num_entries=10, overwrite=False):
"""
Creates num_entries worth a new users
"""
if overwrite:
print("Overwriting Users")
User.objects.all().delete()
count = 0
for _ in range(num_entries):
first_name = fake.first_name()
last_name = fake.last_name()
u = User.objects.create_user(
first_name=first_name,
last_name=last_name,
email=first_name + "." + last_name + "@fakermail.com",
username=first_name + last_name,
password="password"
)
count += 1
percent_complete = count / num_entries * 100
print(
"Adding {} new Users: {:.2f}%".format(
num_entries, percent_complete),
end='\r',
flush=True
)
print()
def seed_polls(num_entries=10, choice_min=2, choice_max=5, overwrite=False):
"""
Seeds num_entries poll with random users as owners
Each poll will be seeded with # choices from choice_min to choice_max
"""
if overwrite:
print('Overwriting polls')
Poll.objects.all().delete()
users = list(User.objects.all())
count = 0
for _ in range(num_entries):
p = Poll(
owner=random.choice(users),
text=fake.paragraph(),
pub_date=datetime.datetime.now()
)
p.save()
num_choices = random.randrange(choice_min, choice_max + 1)
for _ in range(num_choices):
c = Choice(
poll=p,
choice_text=fake.sentence()
).save()
count += 1
percent_complete = count / num_entries * 100
print(
"Adding {} new Polls: {:.2f}%".format(
num_entries, percent_complete),
end='\r',
flush=True
)
print()
def seed_votes():
"""
Creates a new vote on every poll for every user
Voted for choice is selected random.
Deletes all votes prior to adding new ones
"""
Vote.objects.all().delete()
users = User.objects.all()
polls = Poll.objects.all()
count = 0
number_of_new_votes = users.count() * polls.count()
for poll in polls:
choices = list(poll.choice_set.all())
for user in users:
v = Vote(
user=user,
poll=poll,
choice=random.choice(choices)
).save()
count += 1
percent_complete = count / number_of_new_votes * 100
print(
"Adding {} new votes: {:.2f}%".format(
number_of_new_votes, percent_complete),
end='\r',
flush=True
)
print()
def seed_all(num_entries=10, overwrite=False):
"""
Runs all seeder functions. Passes value of overwrite to all
seeder function calls.
"""
start_time = time.time()
# run seeds
seed_users(num_entries=num_entries, overwrite=overwrite)
seed_polls(num_entries=num_entries, overwrite=overwrite)
seed_votes()
# get time
elapsed_time = time.time() - start_time
minutes = int(elapsed_time // 60)
seconds = int(elapsed_time % 60)
print("Script Execution took: {} minutes {} seconds".format(minutes, seconds))
================================================
FILE: static/css/home_style.css
================================================
html, body {
height:100%;
padding: 0;
margin: 0;
color: white;
}
html{
background-image: url('../img/background.jpg');
background-size: cover;
}
body {
background: rgba(0, 0, 0, 0.466);
}
#home-content{
text-align: center;
padding-top: 20%;
}
================================================
FILE: templates/base.html
================================================
{% load static %}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Poll Me | Polls List</title>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css" integrity="sha384-Gn5384xqQ1aoWXA+058RXPxPg6fy4IWvTNh0E263XmFcJlSAwiGgFAW/dAiS6JXm"
crossorigin="anonymous">
<link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.6.3/css/all.css" integrity="sha384-UHRtZLI+pbxtHCWp1t77Bi1L4ZtiqrqD80Kn4Z8NTSRyMA2Fd33n5dQ8lWUE00s/"
crossorigin="anonymous">
{% block custom_css %}{% endblock custom_css %}
</head>
<body>
{% include 'includes/navbar.html' %}
{% block content %}
{% endblock content %}
<!-- All javascript files goes under here -->
<script src="https://code.jquery.com/jquery-3.2.1.slim.min.js" integrity="sha384-KJ3o2DKtIkvYIK3UENzmM7KCkRr/rE9/Qpg6aAZGJwFDMVNA/GpGFF93hXpG5KkN"
crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.12.9/umd/popper.min.js" integrity="sha384-ApNbgh9B+Y1QKtv3Rn7W3mgPxhU9K/ScQsAP7hUibX39j7fakFPskvXusvfa0b4Q"
crossorigin="anonymous"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/js/bootstrap.min.js" integrity="sha384-JZR6Spejh4U02d8jOt6vLEHfe/JQGiRRSQQxSfFWpi1MquVdAyjUar5+76PVCmYl"
crossorigin="anonymous"></script>
</body>
</html>
================================================
FILE: templates/home.html
================================================
{% extends 'base.html' %}
{% load static %}
{% block custom_css %}
<link rel="stylesheet" href="{% static 'css/home_style.css' %}">
{% endblock custom_css %}
{% block content %}
<div class="container">
<div class="row">
<div class="col">
<div id="home-content">
<h1>PollMe - Get Started!</h1>
<h3>Your Voice Matters!</h3>
<hr>
<a class="btn btn-light btn-lg" href="{% url 'polls:list' %}" role="button">Get Started !</a>
</div>
</div>
</div>
</div>
{% endblock content %}
================================================
FILE: templates/includes/navbar.html
================================================
<nav class="navbar navbar-expand-sm navbar-light bg-light mb-5">
<a class="navbar-brand" href="{% url 'home' %}"><i class="fas fa-person-booth"></i></a>
<button class="navbar-toggler d-lg-none" type="button" data-toggle="collapse" data-target="#collapsibleNavId"
aria-controls="collapsibleNavId" aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="collapsibleNavId">
<ul class="navbar-nav mr-auto mt-2 mt-lg-0">
<li class="nav-item active">
<a class="nav-link" href="{% url 'home' %}">Home <span class="sr-only">(current)</span></a>
</li>
{% if request.user.is_authenticated %}
<li class="nav-item">
<a class="nav-link" href="{% url 'polls:list' %}">Polls</a>
</li>
{% endif %}
</ul>
<div class="navbar-nav ml-auto">
{% if request.user.is_authenticated %}
<a class="nav-link" href="{% url 'polls:list_by_user' %}">My Polls</a>
<a class="nav-link" href="{% url 'accounts:logout' %}">Logout</a>
{% else %}
<a class="nav-link" href="{% url 'accounts:login' %}">Login</a>
<a class="nav-link" href="{% url 'accounts:register' %}">Register</a>
{% endif %}
</div>
</div>
</nav>
gitextract_nnisl5fi/
├── .gitignore
├── LICENSE
├── README.md
├── accounts/
│ ├── __init__.py
│ ├── admin.py
│ ├── apps.py
│ ├── forms.py
│ ├── migrations/
│ │ └── __init__.py
│ ├── models.py
│ ├── templates/
│ │ └── accounts/
│ │ ├── login.html
│ │ └── register.html
│ ├── tests.py
│ ├── urls.py
│ └── views.py
├── manage.py
├── pollme/
│ ├── __init__.py
│ ├── settings.py
│ ├── urls.py
│ ├── views.py
│ └── wsgi.py
├── polls/
│ ├── __init__.py
│ ├── admin.py
│ ├── apps.py
│ ├── forms.py
│ ├── migrations/
│ │ ├── 0001_initial.py
│ │ ├── 0002_auto_20231018_1318.py
│ │ └── __init__.py
│ ├── models.py
│ ├── templates/
│ │ └── polls/
│ │ ├── add_choice.html
│ │ ├── add_poll.html
│ │ ├── endpoll.html
│ │ ├── poll_detail.html
│ │ ├── poll_edit.html
│ │ ├── poll_result.html
│ │ └── polls_list.html
│ ├── tests.py
│ ├── urls.py
│ └── views.py
├── requirements.txt
├── seeder.py
├── static/
│ └── css/
│ └── home_style.css
└── templates/
├── base.html
├── home.html
└── includes/
└── navbar.html
SYMBOL INDEX (50 symbols across 13 files)
FILE: accounts/apps.py
class AccountsConfig (line 4) | class AccountsConfig(AppConfig):
FILE: accounts/forms.py
class UserRegistrationForm (line 5) | class UserRegistrationForm(forms.Form):
FILE: accounts/views.py
function login_user (line 9) | def login_user(request):
function logout_user (line 26) | def logout_user(request):
function create_user (line 31) | def create_user(request):
FILE: pollme/views.py
function home (line 4) | def home(request):
FILE: polls/admin.py
class ChoiceInline (line 5) | class ChoiceInline(admin.TabularInline): # or admin.StackedInline for a...
class PollAdmin (line 10) | class PollAdmin(admin.ModelAdmin):
class ChoiceAdmin (line 19) | class ChoiceAdmin(admin.ModelAdmin):
class VoteAdmin (line 26) | class VoteAdmin(admin.ModelAdmin):
FILE: polls/apps.py
class PollsConfig (line 4) | class PollsConfig(AppConfig):
FILE: polls/forms.py
class PollAddForm (line 5) | class PollAddForm(forms.ModelForm):
class Meta (line 12) | class Meta:
class EditPollForm (line 20) | class EditPollForm(forms.ModelForm):
class Meta (line 21) | class Meta:
class ChoiceAddForm (line 29) | class ChoiceAddForm(forms.ModelForm):
class Meta (line 30) | class Meta:
FILE: polls/migrations/0001_initial.py
class Migration (line 9) | class Migration(migrations.Migration):
FILE: polls/migrations/0002_auto_20231018_1318.py
class Migration (line 7) | class Migration(migrations.Migration):
FILE: polls/models.py
class Poll (line 7) | class Poll(models.Model):
method user_can_vote (line 14) | def user_can_vote(self, user):
method get_vote_count (line 25) | def get_vote_count(self):
method get_result_dict (line 28) | def get_result_dict(self):
method __str__ (line 47) | def __str__(self):
class Choice (line 51) | class Choice(models.Model):
method get_vote_count (line 58) | def get_vote_count(self):
method __str__ (line 61) | def __str__(self):
class Vote (line 65) | class Vote(models.Model):
method __str__ (line 72) | def __str__(self):
FILE: polls/tests.py
class PollModelTest (line 9) | class PollModelTest(TestCase):
method test_user_can_vote (line 10) | def test_user_can_vote(self):
class PollViewTest (line 20) | class PollViewTest(TestCase):
method test_home (line 21) | def test_home(self):
method test_login (line 25) | def test_login(self):
method test_register (line 32) | def test_register(self):
FILE: polls/views.py
function polls_list (line 12) | def polls_list(request):
function list_by_user (line 44) | def list_by_user(request):
function polls_add (line 58) | def polls_add(request):
function polls_edit (line 86) | def polls_edit(request, poll_id):
function polls_delete (line 106) | def polls_delete(request, poll_id):
function add_choice (line 117) | def add_choice(request, poll_id):
function choice_edit (line 140) | def choice_edit(request, choice_id):
function choice_delete (line 166) | def choice_delete(request, choice_id):
function poll_detail (line 177) | def poll_detail(request, poll_id):
function poll_vote (line 191) | def poll_vote(request, poll_id):
function end_poll (line 213) | def end_poll(request, poll_id):
FILE: seeder.py
function seed_users (line 10) | def seed_users(num_entries=10, overwrite=False):
function seed_polls (line 39) | def seed_polls(num_entries=10, choice_min=2, choice_max=5, overwrite=Fal...
function seed_votes (line 73) | def seed_votes():
function seed_all (line 103) | def seed_all(num_entries=10, overwrite=False):
Condensed preview — 44 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (60K chars).
[
{
"path": ".gitignore",
"chars": 78,
"preview": "*.log\n*.pot\n*.pyc\n__pycache__/\nlocal_settings.py\ndb.sqlite3\nmedia\nvenv\n.vscode"
},
{
"path": "LICENSE",
"chars": 1070,
"preview": "MIT License\n\nCopyright (c) 2019 Mahmudul Alam\n\nPermission is hereby granted, free of charge, to any person obtaining a c"
},
{
"path": "README.md",
"chars": 3683,
"preview": "# Django-Poll-App\n\nDjango poll app is a full featured polling app. You have to register in this app to show the polls an"
},
{
"path": "accounts/__init__.py",
"chars": 0,
"preview": ""
},
{
"path": "accounts/admin.py",
"chars": 63,
"preview": "from django.contrib import admin\n\n# Register your models here.\n"
},
{
"path": "accounts/apps.py",
"chars": 91,
"preview": "from django.apps import AppConfig\n\n\nclass AccountsConfig(AppConfig):\n name = 'accounts'\n"
},
{
"path": "accounts/forms.py",
"chars": 822,
"preview": "from django import forms\nfrom django.contrib.auth.models import User\n\n\nclass UserRegistrationForm(forms.Form):\n usern"
},
{
"path": "accounts/migrations/__init__.py",
"chars": 0,
"preview": ""
},
{
"path": "accounts/models.py",
"chars": 57,
"preview": "from django.db import models\n\n# Create your models here.\n"
},
{
"path": "accounts/templates/accounts/login.html",
"chars": 2055,
"preview": "{% extends 'base.html' %}\n\n{% block content %}\n <div class=\"vh-100 d-flex justify-content-center align-items-center p"
},
{
"path": "accounts/templates/accounts/register.html",
"chars": 1026,
"preview": "{% extends 'base.html' %}\n\n{% block content %}\n<div class=\"container\">\n <div class=\"row center\">\n <div class=\""
},
{
"path": "accounts/tests.py",
"chars": 60,
"preview": "from django.test import TestCase\n\n# Create your tests here.\n"
},
{
"path": "accounts/urls.py",
"chars": 254,
"preview": "from django.urls import path\nfrom . import views\n\napp_name = \"accounts\"\n\nurlpatterns=[\n path('login/', views.login_us"
},
{
"path": "accounts/views.py",
"chars": 2825,
"preview": "from django.contrib.auth import authenticate, login, logout\nfrom django.shortcuts import render, redirect\nfrom django.co"
},
{
"path": "manage.py",
"chars": 538,
"preview": "#!/usr/bin/env python\nimport os\nimport sys\n\nif __name__ == '__main__':\n os.environ.setdefault('DJANGO_SETTINGS_MODULE"
},
{
"path": "pollme/__init__.py",
"chars": 0,
"preview": ""
},
{
"path": "pollme/settings.py",
"chars": 3301,
"preview": "\"\"\"\nDjango settings for pollme project.\n\nGenerated by 'django-admin startproject' using Django 2.1.5.\n\nFor more informat"
},
{
"path": "pollme/urls.py",
"chars": 949,
"preview": "\"\"\"pollme URL Configuration\n\nThe `urlpatterns` list routes URLs to views. For more information please see:\n https://d"
},
{
"path": "pollme/views.py",
"chars": 95,
"preview": "from django.shortcuts import render\n\n\ndef home(request):\n return render(request,'home.html')"
},
{
"path": "pollme/wsgi.py",
"chars": 389,
"preview": "\"\"\"\nWSGI config for pollme project.\n\nIt exposes the WSGI callable as a module-level variable named ``application``.\n\nFor"
},
{
"path": "polls/__init__.py",
"chars": 0,
"preview": ""
},
{
"path": "polls/admin.py",
"chars": 959,
"preview": "from django.contrib import admin\nfrom .models import Poll, Choice, Vote\n\n\nclass ChoiceInline(admin.TabularInline): # or"
},
{
"path": "polls/apps.py",
"chars": 85,
"preview": "from django.apps import AppConfig\n\n\nclass PollsConfig(AppConfig):\n name = 'polls'\n"
},
{
"path": "polls/forms.py",
"chars": 1083,
"preview": "from django import forms\nfrom .models import Poll, Choice\n\n\nclass PollAddForm(forms.ModelForm):\n\n choice1 = forms.Cha"
},
{
"path": "polls/migrations/0001_initial.py",
"chars": 1943,
"preview": "# Generated by Django 3.1.5 on 2021-01-29 16:38\n\nfrom django.conf import settings\nfrom django.db import migrations, mode"
},
{
"path": "polls/migrations/0002_auto_20231018_1318.py",
"chars": 1264,
"preview": "# Generated by Django 3.1.14 on 2023-10-18 07:18\n\nfrom django.db import migrations, models\nimport django.utils.timezone\n"
},
{
"path": "polls/migrations/__init__.py",
"chars": 0,
"preview": ""
},
{
"path": "polls/models.py",
"chars": 2312,
"preview": "from django.contrib.auth.models import User\nfrom django.db import models\nfrom django.utils import timezone\nimport secret"
},
{
"path": "polls/templates/polls/add_choice.html",
"chars": 1391,
"preview": "{% extends 'base.html' %}\n\n{% block content %}\n<div class=\"container\">\n <div class=\"row center\">\n <div class=\""
},
{
"path": "polls/templates/polls/add_poll.html",
"chars": 1026,
"preview": "{% extends 'base.html' %}\n\n{% block content %}\n<div class=\"container\">\n <div class=\"row center\">\n <div class=\""
},
{
"path": "polls/templates/polls/endpoll.html",
"chars": 1623,
"preview": "{% extends 'base.html' %}\n\n\n{% block content %}\n<div class=\"container\">\n {% if messages %}\n <div class=\"messages\">"
},
{
"path": "polls/templates/polls/poll_detail.html",
"chars": 1124,
"preview": "{% extends 'base.html' %}\n\n\n{% block content %}\n<div class=\"container\">\n <h1>Polls details page</h1>\n {% if messag"
},
{
"path": "polls/templates/polls/poll_edit.html",
"chars": 1942,
"preview": "{% extends 'base.html' %}\n\n{% block content %}\n<div class=\"container\">\n <div class=\"row center\">\n <div class=\""
},
{
"path": "polls/templates/polls/poll_result.html",
"chars": 1973,
"preview": "{% extends 'base.html' %}\n\n{% block content %}\n<div class=\"container\">\n {% if messages %}\n <div class=\"messages\">\n"
},
{
"path": "polls/templates/polls/polls_list.html",
"chars": 3914,
"preview": "{% extends 'base.html' %}\n\n{% block content %}\n<div class=\"container\">\n <div class=\"row\">\n <div class=\"col-md-"
},
{
"path": "polls/tests.py",
"chars": 1493,
"preview": "from django.contrib.auth import authenticate\nfrom django.contrib.auth.models import User\nfrom django.test import TestCas"
},
{
"path": "polls/urls.py",
"chars": 837,
"preview": "from django.urls import path\nfrom . import views\n\napp_name = \"polls\"\n\nurlpatterns = [\n path('list/', views.polls_list"
},
{
"path": "polls/views.py",
"chars": 7336,
"preview": "from django.shortcuts import render, get_object_or_404, redirect\nfrom django.contrib.auth.decorators import login_requir"
},
{
"path": "requirements.txt",
"chars": 63,
"preview": "asgiref==3.3.1\n\"Django>=4.2,<4.3\"\npytz==2020.5\nsqlparse==0.4.4\n"
},
{
"path": "seeder.py",
"chars": 3472,
"preview": "from polls.models import Choice, Poll, Vote\nfrom django.contrib.auth.models import User\nimport datetime\nimport random\nim"
},
{
"path": "static/css/home_style.css",
"chars": 280,
"preview": "html, body {\n height:100%;\n padding: 0;\n margin: 0;\n color: white;\n }\nhtml{\n background-image: url('../i"
},
{
"path": "templates/base.html",
"chars": 1546,
"preview": "{% load static %}\n<!DOCTYPE html>\n<html lang=\"en\">\n\n<head>\n <meta charset=\"UTF-8\">\n <meta name=\"viewport\" content="
},
{
"path": "templates/home.html",
"chars": 585,
"preview": "{% extends 'base.html' %}\n{% load static %}\n{% block custom_css %}\n<link rel=\"stylesheet\" href=\"{% static 'css/home_styl"
},
{
"path": "templates/includes/navbar.html",
"chars": 1422,
"preview": "<nav class=\"navbar navbar-expand-sm navbar-light bg-light mb-5\">\n <a class=\"navbar-brand\" href=\"{% url 'home' %}\"><i "
}
]
About this extraction
This page contains the full source code of the devmahmud/Django-Poll-App GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 44 files (53.7 KB), approximately 13.9k tokens, and a symbol index with 50 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.
Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.