Merge pull request #22 from Sosokker/iteration2

Add new Feature according to Iteration 2 Plan / Externalize Secret Variable
This commit is contained in:
Sirin Puenggun 2023-09-05 21:59:54 +07:00 committed by GitHub
commit 356449c396
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 135 additions and 10 deletions

View File

@ -28,6 +28,8 @@ or
**Don't forget to change `your_secret_key` to your secret key (without quote)**
**You can look at `sample.env` for more information and others environment variables to set.**
4. Run these commands
```bash
python manage.py migrate

View File

@ -11,7 +11,7 @@ https://docs.djangoproject.com/en/4.2/ref/settings/
"""
from pathlib import Path
from decouple import config
from decouple import config, Csv
# Build paths inside the project like this: BASE_DIR / 'subdir'.
BASE_DIR = Path(__file__).resolve().parent.parent
@ -20,14 +20,15 @@ BASE_DIR = Path(__file__).resolve().parent.parent
# Quick-start development settings - unsuitable for production
# See https://docs.djangoproject.com/en/4.2/howto/deployment/checklist/
# SECURITY WARNING: keep the secret key used in production secret!
SECRET_KEY = config('SECRET_KEY', default='fake-secret-key')
#! SECURITY WARNING: keep the secret key used in production secret!
SECRET_KEY = config('SECRET_KEY', default='k2pd1p)zwe0qy0k25=sli+7+n^vd-0h*&6vga6oldq=781+7qw')
# SECURITY WARNING: don't run with debug turned on in production!
DEBUG = True
#! SECURITY WARNING: don't run with debug turned on in production!
DEBUG = config('DEBUG', default=False, cast=bool)
ALLOWED_HOSTS = []
ALLOWED_HOSTS = config('ALLOWED_HOSTS', default='*', cast=Csv())
TIME_ZONE = config('TIME_ZONE', default='Asia/Bangkok', cast=str)
# Application definition

View File

@ -0,0 +1,24 @@
# Generated by Django 4.2.4 on 2023-09-05 13:47
from django.db import migrations, models
import django.utils.timezone
class Migration(migrations.Migration):
dependencies = [
('polls', '0001_initial'),
]
operations = [
migrations.AddField(
model_name='question',
name='end_date',
field=models.DateTimeField(null=True, verbose_name='date ended'),
),
migrations.AlterField(
model_name='question',
name='pub_date',
field=models.DateTimeField(default=django.utils.timezone.now, verbose_name='date published'),
),
]

View File

@ -26,7 +26,8 @@ class Question(models.Model):
"""
question_text = models.CharField(max_length=200)
pub_date = models.DateTimeField("date published")
pub_date = models.DateTimeField("date published", default=timezone.now)
end_date = models.DateTimeField("date ended", null=True)
def was_published_recently(self):
"""
@ -53,6 +54,29 @@ class Question(models.Model):
"""
return self.question_text
def is_published(self):
"""
Checks if the question is published or not.
Returns:
bool: True if the question is published, else False.
"""
now = timezone.now()
return now >= self.pub_date
def can_vote(self):
"""
Checks if the question can be voted on or not.
Returns:
bool: True if the question is published and not ended, else False.
"""
now = timezone.now()
if self.end_date is None:
return self.pub_date <= now
else:
return self.pub_date <= now <= self.end_date
class Choice(models.Model):
"""

View File

@ -10,7 +10,7 @@
</section>
<section class="polls-section">
<h2>Recent Polls</h2>
<p class="total-polls">Total number of polls: {{ total_polls }}</p>
<p class="total-polls">Total number of polls: {{ total_open_polls }}</p>
<div class="poll-cards">
{% if latest_question_list %}
{% for question in latest_question_list %}

View File

@ -37,6 +37,64 @@ class QuestionModelTests(TestCase):
self.assertIs(recent_question.was_published_recently(), True)
def test_is_published_with_future_question(self):
"""
is_published() should return False for questions whos pub_date is in the
future.
"""
future_date = timezone.now() + datetime.timedelta(days=30)
future_question = Question(pub_date=future_date)
self.assertIs(future_question.is_published(), False)
def test_is_published_with_past_question(self):
"""
is_published() should return True for questions whose pub_date is in the
past.
"""
past_date = timezone.now() - datetime.timedelta(days=1)
past_question = Question(pub_date=past_date)
self.assertIs(past_question.is_published(), True)
def test_can_vote_with_question_not_ended(self):
"""
can_vote() should return True for questions that are published and have not
ended.
"""
pub_date = timezone.now() - datetime.timedelta(hours=1)
end_date = timezone.now() + datetime.timedelta(hours=1)
question = Question(pub_date=pub_date, end_date=end_date)
self.assertIs(question.can_vote(), True)
def test_can_vote_with_question_ended(self):
"""
can_vote() should return False for questions that are published but have
ended.
"""
pub_date = timezone.now() - datetime.timedelta(hours=2)
end_date = timezone.now() - datetime.timedelta(hours=1)
question = Question(pub_date=pub_date, end_date=end_date)
self.assertIs(question.can_vote(), False)
def test_can_vote_with_question_no_end_date(self):
"""
can_vote() should return True for questions that are published and have no
specified end date.
"""
pub_date = timezone.now() - datetime.timedelta(hours=1)
question = Question(pub_date=pub_date, end_date=None)
self.assertIs(question.can_vote(), True)
def test_can_vote_with_question_ending_in_future(self):
"""
can_vote() should return True for questions that are published and
the current time is within the allowed voting period.
"""
pub_date = timezone.now() - datetime.timedelta(hours=1)
end_date = timezone.now() + datetime.timedelta(hours=2)
question = Question(pub_date=pub_date, end_date=end_date)
self.assertIs(question.can_vote(), True)
def create_question(question_text, days):
"""
Create a question with the given `question_text` and published the

View File

@ -17,8 +17,14 @@ class HomeView(TemplateView):
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context['latest_question_list'] = Question.objects.filter(pub_date__lte=timezone.now()).order_by("-pub_date")[:5]
context['total_polls'] = Question.objects.count()
all_questions = Question.objects.all()
#* Check if the question is published and can be voted. Then, sort by pub_date
published_questions = [q for q in all_questions if q.is_published() and q.can_vote()]
latest_published_questions = sorted(published_questions, key=lambda q: q.pub_date, reverse=True)[:5]
context['latest_question_list'] = latest_published_questions
context['total_open_polls'] = sum(1 for q in published_questions if q.end_date is None)
context['total_polls'] = all_questions.count()
return context

Binary file not shown.

10
sample.env Normal file
View File

@ -0,0 +1,10 @@
# Copy this file to .env and edit the values
# Create a secret key using (todo: how to create a secret key?)
SECRET_KEY = secret-key-value-without-quotes
# Set DEBUG to True for development, False for actual use
DEBUG = False
# ALLOWED_HOSTS is a comma-separated list of hosts that can access the app.
# You can use wildcard chars (*) and IP addresses. Use * for any host.
ALLOWED_HOSTS = *.ku.th, localhost, 127.0.0.1, ::1
# Your timezone
TIME_ZONE = Asia/Bangkok