mirror of
https://github.com/Sosokker/ku-polls.git
synced 2025-12-19 05:24:05 +01:00
Merge pull request #22 from Sosokker/iteration2
Add new Feature according to Iteration 2 Plan / Externalize Secret Variable
This commit is contained in:
commit
356449c396
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
|
||||
@ -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'),
|
||||
),
|
||||
]
|
||||
@ -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):
|
||||
"""
|
||||
|
||||
@ -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 %}
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
|
||||
|
||||
BIN
requirements.txt
BIN
requirements.txt
Binary file not shown.
10
sample.env
Normal file
10
sample.env
Normal 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
|
||||
Loading…
Reference in New Issue
Block a user