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.

Getting Started

These instructions will get you a copy of the project up and running on your local machine for development and testing purposes.

Prerequisites

python== 3.5 or up and django==2.0 or up

Installing

open terminal and type
git clone https://github.com/devmahmud/Django-poll-app.git

or simply download using the url below

https://github.com/devmahmud/Django-poll-app.git

To migrate the database open terminal in project directory and type

python manage.py makemigrations
python manage.py migrate

To use admin panel you need to create superuser using this command

python manage.py createsuperuser

To Create some dummy text data for your app follow the step below:

pip install faker python manage.py shell import seeder seeder.seed_all(30)

Here 30 is a number of entry. You can use it as your own

To run the program in local server use the following command

python manage.py runserver

Then go to http://127.0.0.1:8000 in your browser

Project snapshot

Home page

Login Page

Registration Page

Poll List Page

Poll Add Page

Polling page

Poll Result Page

Poll Edit Page

Choice Update Delete Page

Author

Mahmudul alam
Email: expelmahmud@gmail.com

========Thank You !!!=========

================================================ 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 %}

Login

{% if messages %}
{% for message in messages %}
{{ message }}
{% endfor %}
{% endif %}
{% csrf_token %}

Don't have an account? Sign Up

{% endblock %} ================================================ FILE: accounts/templates/accounts/register.html ================================================ {% extends 'base.html' %} {% block content %}

Already have an account? Login Here

{% if messages %}
{% for message in messages %}
{{ message }}
{% endfor %}
{% endif %}
{% csrf_token %} {{ form.as_p }}
{% 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 %}
{% if edit_choice %}

Update choice

{% else %}

Add new choice

{% endif %} {% if messages %}
    {% for message in messages %}
  • {{ message }}
  • {% endfor %}
{% endif %}
{% csrf_token %} {% for field in form %}
{{ field.errors }} {{ field.label_tag }} {{ field }}
{% endfor %} {% if edit_choice %} Delete {% else %} {% endif %}
{% endblock %} ================================================ FILE: polls/templates/polls/add_poll.html ================================================ {% extends 'base.html' %} {% block content %}

Create new poll

{% if messages %}
    {% for message in messages %}
  • {{ message }}
  • {% endfor %}
{% endif %}
{% csrf_token %} {% for field in form %}
{{ field.errors }} {{ field.label_tag }} {{ field }}
{% endfor %} Back
{% endblock %} ================================================ FILE: polls/templates/polls/endpoll.html ================================================ {% extends 'base.html' %} {% block content %}
{% if messages %}
{% for message in messages %}
{{ message }}
{% endfor %}
{% else %}

Result for: {{ poll.text }}

{% for choice in poll.get_result_dict %}
{{ choice.text }}-{{ choice.percentage|floatformat }}%
{% endfor %}
    {% for choice in poll.choice_set.all %}
  • {{ choice.choice_text }} {{ choice.get_vote_count }}
  • {% endfor %}
{% endif %} Back To Polls
{% endblock content %} ================================================ FILE: polls/templates/polls/poll_detail.html ================================================ {% extends 'base.html' %} {% block content %}

Polls details page

{% if messages %}
{% for message in messages %}
{{ message }}
{% endfor %}
{% endif %}

{{ poll }}

{% csrf_token %} {% for choice in poll.choice_set.all %}
{% endfor %} Cancel
{% endblock content %} ================================================ FILE: polls/templates/polls/poll_edit.html ================================================ {% extends 'base.html' %} {% block content %}

Edit poll

{% if messages %} {% if messages %}
{% for message in messages %}
{{ message }}
{% endfor %}
{% endif %} {% endif %}
{% csrf_token %} {% for field in form %}
{{ field.errors }} {{ field.label_tag }} {{ field }}
{% endfor %} Delete Add Choice

Choices


    {% for choice in poll.choice_set.all %}
  •   {{ choice.choice_text }}
  • {% endfor %}
{% endblock %} ================================================ FILE: polls/templates/polls/poll_result.html ================================================ {% extends 'base.html' %} {% block content %}
{% if messages %}
{% for message in messages %}
{{ message }}
{% endfor %}
{% else %}
{% if poll.active %}

Result for: {{ poll.text }}

{% else %}

"{{ poll.text }}" Has Ended Polling!

{% endif %}

Total: {{ poll.get_vote_count }} votes

{% for choice in poll.get_result_dict %}
{{choice.text|truncatewords:2}}-{{choice.percentage|floatformat}}%
{% endfor %}
    {% for choice in poll.choice_set.all %}
  • {{ choice.choice_text }} {{ choice.get_vote_count }}
  • {% endfor %}
{% endif %} Back To Polls
{% endblock content %} ================================================ FILE: polls/templates/polls/polls_list.html ================================================ {% extends 'base.html' %} {% block content %}

Welcome to polls List!

{% if messages %}
{% for message in messages %}
{{ message }}
{% endfor %}
{% endif %} Name Date Vote Add
{% if polls.paginator.num_pages > 1 %} {% endif %}
{% 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//', views.polls_edit, name='edit'), path('delete//', views.polls_delete, name='delete_poll'), path('end//', views.end_poll, name='end_poll'), path('edit//choice/add/', views.add_choice, name='add_choice'), path('edit/choice//', views.choice_edit, name='choice_edit'), path('delete/choice//', views.choice_delete, name='choice_delete'), path('/', views.poll_detail, name='detail'), path('/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 %} Poll Me | Polls List {% block custom_css %}{% endblock custom_css %} {% include 'includes/navbar.html' %} {% block content %} {% endblock content %} ================================================ FILE: templates/home.html ================================================ {% extends 'base.html' %} {% load static %} {% block custom_css %} {% endblock custom_css %} {% block content %}

PollMe - Get Started!

Your Voice Matters!


Get Started !
{% endblock content %} ================================================ FILE: templates/includes/navbar.html ================================================