diff --git a/sami/django/mysite2/polls/.#models.py b/sami/django/mysite2/polls/.#models.py deleted file mode 120000 index 3884ade..0000000 --- a/sami/django/mysite2/polls/.#models.py +++ /dev/null @@ -1 +0,0 @@ -sami@afro-linux-lenovo-b50-30.8898:1594292241 \ No newline at end of file diff --git a/sami/django/mysite2/polls/models.py b/sami/django/mysite2/polls/models.py index 1914ee2..a7c5580 100644 --- a/sami/django/mysite2/polls/models.py +++ b/sami/django/mysite2/polls/models.py @@ -1,7 +1,7 @@ -from django.utils import timezone -from django.db import models import datetime +from django.db import models +from django.utils import timezone # Create your models here. @@ -9,19 +9,20 @@ import datetime class Question(models.Model): question_text = models.CharField(max_length=200) pub_date = models.DateTimeField('date published') - def __str__(self): return self.question_text def was_published_recently(self): - return self.pub_date >= timezone.now() -datetime.timedelta(days=1) + now = timezone.now() + return now - datetime.timedelta(days=1) <= self.pub_date <= now + #def was_published_recently(self): + #return self.pub_date >= timezone.now() - datetime.timedelta(days=1) + + class Choice(models.Model): question = models.ForeignKey(Question, on_delete=models.CASCADE) choice_text = models.CharField(max_length=200) votes = models.IntegerField(default=0) - def __str__(self): return self.choice_text - - diff --git a/sami/django/mysite2/polls/templates/detail.html b/sami/django/mysite2/polls/templates/detail.html new file mode 100644 index 0000000..c225d49 --- /dev/null +++ b/sami/django/mysite2/polls/templates/detail.html @@ -0,0 +1,13 @@ +

{{ question.question_text }}

+ +{% if error_message %}

{{ error_message }}

{% endif %} + +
+{% csrf_token %} +{% for choice in question.choice_set.all %} + +
+{% endfor %} + +
+p diff --git a/sami/django/mysite2/polls/templates/polls/detail.html b/sami/django/mysite2/polls/templates/polls/detail.html index 6667640..3e55544 100644 --- a/sami/django/mysite2/polls/templates/polls/detail.html +++ b/sami/django/mysite2/polls/templates/polls/detail.html @@ -1 +1,12 @@ -{{ question }} +

{{ question.question_text }}

+ +{% if error_message %}

{{ error_message }}

{% endif %} + +
+{% csrf_token %} +{% for choice in question.choice_set.all %} + +
+{% endfor %} + +
diff --git a/sami/django/mysite2/polls/templates/polls/index.html b/sami/django/mysite2/polls/templates/polls/index.html index 71c2249..4560139 100644 --- a/sami/django/mysite2/polls/templates/polls/index.html +++ b/sami/django/mysite2/polls/templates/polls/index.html @@ -1,22 +1,9 @@ {% if latest_question_list %} {% else %}

No polls are available.

{% endif %} - -

{{ question.question_text }}

- -{% if error_message %}

{{ error_message }}

{% endif %} - -
-{% csrf_token %} -{% for choice in question.choice_set.all %} - -
-{% endfor %} - -
diff --git a/sami/django/mysite2/polls/tests.py b/sami/django/mysite2/polls/tests.py index 7ce503c..3604a06 100644 --- a/sami/django/mysite2/polls/tests.py +++ b/sami/django/mysite2/polls/tests.py @@ -1,3 +1,128 @@ -from django.test import TestCase +import datetime -# Create your tests here. +from django.test import TestCase +from django.utils import timezone +from django.urls import reverse + +from .models import Question + + +class QuestionModelTests(TestCase): + + def test_was_published_recently_with_future_question(self): + """ + was_published_recently() returns False for questions whose pub_date + is in the future. + """ + time = timezone.now() + datetime.timedelta(days=30) + future_question = Question(pub_date=time) + self.assertIs(future_question.was_published_recently(), False) + + def test_was_published_recently_with_old_question(self): + """ + was_published_recently() returns False for questions whose pub_date + is older than 1 day. + """ + time = timezone.now() - datetime.timedelta(days=1, seconds=1) + old_question = Question(pub_date=time) + self.assertIs(old_question.was_published_recently(), False) + + def test_was_published_recently_with_recent_question(self): + """ + was_published_recently() returns True for questions whose pub_date + is within the last day. + """ + time = timezone.now() - datetime.timedelta(hours=23, minutes=59, seconds=59) + recent_question = Question(pub_date=time) + self.assertIs(recent_question.was_published_recently(), True) + + + +def create_question(question_text, days): + """ + Create a question with the given `question_text` and published the + given number of `days` offset to now (negative for questions published + in the past, positive for questions that have yet to be published). + """ + time = timezone.now() + datetime.timedelta(days=days) + return Question.objects.create(question_text=question_text, pub_date=time) + + +class QuestionIndexViewTests(TestCase): + def test_no_questions(self): + """ + If no questions exist, an appropriate message is displayed. + """ + response = self.client.get(reverse('polls:index')) + self.assertEqual(response.status_code, 200) + self.assertContains(response, "No polls are available.") + self.assertQuerysetEqual(response.context['latest_question_list'], []) + + def test_past_question(self): + """ + Questions with a pub_date in the past are displayed on the + index page. + """ + create_question(question_text="Past question.", days=-30) + response = self.client.get(reverse('polls:index')) + self.assertQuerysetEqual( + response.context['latest_question_list'], + [''] + ) + + def test_future_question(self): + """ + Questions with a pub_date in the future aren't displayed on + the index page. + """ + create_question(question_text="Future question.", days=30) + response = self.client.get(reverse('polls:index')) + self.assertContains(response, "No polls are available.") + self.assertQuerysetEqual(response.context['latest_question_list'], []) + + def test_future_question_and_past_question(self): + """ + Even if both past and future questions exist, only past questions + are displayed. + """ + create_question(question_text="Past question.", days=-30) + create_question(question_text="Future question.", days=30) + response = self.client.get(reverse('polls:index')) + self.assertQuerysetEqual( + response.context['latest_question_list'], + [''] + ) + + def test_two_past_questions(self): + """ + The questions index page may display multiple questions. + """ + create_question(question_text="Past question 1.", days=-30) + create_question(question_text="Past question 2.", days=-5) + response = self.client.get(reverse('polls:index')) + self.assertQuerysetEqual( + response.context['latest_question_list'], + ['', ''] + ) + + +class QuestionDetailViewTests(TestCase): + def test_future_question(self): + """ + The detail view of a question with a pub_date in the future + returns a 404 not found. + """ + future_question = create_question(question_text='Future question.', days=5) + url = reverse('polls:detail', args=(future_question.id,)) + response = self.client.get(url) + self.assertEqual(response.status_code, 404) + + def test_past_question(self): + """ + The detail view of a question with a pub_date in the past + displays the question's text. + """ + past_question = create_question(question_text='Past Question.', days=-5) + url = reverse('polls:detail', args=(past_question.id,)) + response = self.client.get(url) + self.assertContains(response, past_question.question_text) diff --git a/sami/django/mysite2/polls/urls.py b/sami/django/mysite2/polls/urls.py index 0b66ce8..eff2be0 100644 --- a/sami/django/mysite2/polls/urls.py +++ b/sami/django/mysite2/polls/urls.py @@ -1,13 +1,11 @@ from django.urls import path -# Here is importing the views which I modified + from . import views + app_name = 'polls' urlpatterns = [ - path('', views.index, name='index'), - # ex: /polls/5/ - path('/', views.detail, name='detail'), - # ex: /polls/5/results/ - path('/results/', views.results, name='results'), - # ex: /polls/5/vote/ + path('', views.IndexView.as_view(), name='index'), + path('/', views.DetailView.as_view(), name='detail'), + path('/results/', views.ResultsView.as_view(), name='results'), path('/vote/', views.vote, name='vote'), ] diff --git a/sami/django/mysite2/polls/views.py b/sami/django/mysite2/polls/views.py index b018678..68cf7b5 100644 --- a/sami/django/mysite2/polls/views.py +++ b/sami/django/mysite2/polls/views.py @@ -1,38 +1,61 @@ -# Here is the fist view add by Sami from Diesbach -from django.shortcuts import render -from django.http import HttpResponse -from django.shortcuts import Http404 -from .models import Choice, Question +from django.http import HttpResponse, HttpResponseRedirect +#from django.http import Http404 from django.template import loader from django.shortcuts import get_object_or_404, render -from django.http import HttpResponse, HttpResponseRedirect from django.urls import reverse from django.views import generic +from django.utils import timezone + +from .models import Choice, Question - +#def index(request): +# latest_question_list = Question.objects.order_by('-pub_date')[:5] +# context = {'latest_question_list': latest_question_list} +# return render(request, 'polls/index.html', context) class IndexView(generic.ListView): template_name = 'polls/index.html' context_object_name = 'latest_question_list' def get_queryset(self): - """Return the last five published questions.""" - return Question.objects.order_by('-pub_date')[:5] + """ + Return the last five published questions (not including those set to be + published in the future). + """ + return Question.objects.filter( + pub_date__lte=timezone.now() + ).order_by('-pub_date')[:5] + #"""Return the last five published questions.""" + #return Question.objects.order_by('-pub_date')[:5] +#def detail(request, question_id): +# #return HttpResponse("You're looking at question %s." % question_id) +# question = get_object_or_404(Question, pk=question_id) +# return render(request, 'polls/detail.html', {'question': question}) class DetailView(generic.DetailView): model = Question template_name = 'polls/detail.html' + + def get_queryset(self): + """ + Excludes any questions that aren't published yet. + """ + return Question.objects.filter(pub_date__lte=timezone.now()) +#def results(request, question_id): +# #response = "You're looking at the results of question %s." +# #return HttpResponse(response % question_id) +# question = get_object_or_404(Question, pk=question_id) +# return render(request, 'polls/results.html', {'question': question}) class ResultsView(generic.DetailView): model = Question template_name = 'polls/results.html' - - def vote(request, question_id): + #return HttpResponse("You're voting on question %s." % question_id) question = get_object_or_404(Question, pk=question_id) try: selected_choice = question.choice_set.get(pk=request.POST['choice']) @@ -49,5 +72,3 @@ def vote(request, question_id): # with POST data. This prevents data from being posted twice if a # user hits the Back button. return HttpResponseRedirect(reverse('polls:results', args=(question.id,))) - -