diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..67e78e9 --- /dev/null +++ b/.gitignore @@ -0,0 +1,41 @@ +# Numerous always-ignore extensions +*.pyc +*.diff +*.err +*.orig +*.log +*.rej +*.swo +*.swp +*.vi +*.cache +*.egg-info +*~ +*# + +# OS or Editor folders +.DS_Store +Thumbs.db +.cache +.project +.settings +.tmproj +*.esproj +nbproject +*.sublime-project +*.sublime-workspace +.tm_properties +._* + +# Folders to ignore +.hg +.svn +.CVS +.idea +_assets +_design +_content +_tmp +dist +build +_build diff --git a/mysite/__init__.pyc b/mysite/__init__.pyc deleted file mode 100644 index 30808d0..0000000 Binary files a/mysite/__init__.pyc and /dev/null differ diff --git a/mysite/settings.py b/mysite/settings.py index 8e12620..121685b 100644 --- a/mysite/settings.py +++ b/mysite/settings.py @@ -103,11 +103,15 @@ # Python dotted path to the WSGI application used by Django's runserver. WSGI_APPLICATION = 'mysite.wsgi.application' +import os.path +BASE_PATH = os.path.normpath(os.path.dirname(__file__)) + TEMPLATE_DIRS = ( # Put strings here, like "/home/html/django_templates" or "C:/www/django/templates". # Always use forward slashes, even on Windows. - # Don't forget to use absolute paths, not relative paths. -) + # Don't forget to use absolute paths, not relative paths. + BASE_PATH + "/templates/", + ) INSTALLED_APPS = ( 'django.contrib.auth', @@ -117,7 +121,7 @@ 'django.contrib.messages', 'django.contrib.staticfiles', # Uncomment the next line to enable the admin: - # 'django.contrib.admin', + 'django.contrib.admin', # Uncomment the next line to enable admin documentation: # 'django.contrib.admindocs', 'polls', diff --git a/mysite/settings.pyc b/mysite/settings.pyc deleted file mode 100644 index 54c54fe..0000000 Binary files a/mysite/settings.pyc and /dev/null differ diff --git a/mysite/templates/admin/base_site.html b/mysite/templates/admin/base_site.html new file mode 100644 index 0000000..0717edf --- /dev/null +++ b/mysite/templates/admin/base_site.html @@ -0,0 +1,10 @@ +{% extends "admin/base.html" %} +{% load i18n %} + +{% block title %}MySite Corp Global Industries {{ title }} | {% trans 'Django site admin' %}e{% endblock %} + +{% block branding %} +

MySite Corp Global Industries {% trans 'Django administration' %}

+{% endblock %} + +{% block nav-global %}{% endblock %} diff --git a/mysite/urls.py b/mysite/urls.py index ebbc31d..b884696 100644 --- a/mysite/urls.py +++ b/mysite/urls.py @@ -1,17 +1,9 @@ from django.conf.urls import patterns, include, url -# Uncomment the next two lines to enable the admin: -# from django.contrib import admin -# admin.autodiscover() +from django.contrib import admin +admin.autodiscover() urlpatterns = patterns('', - # Examples: - # url(r'^$', 'mysite.views.home', name='home'), - # url(r'^mysite/', include('mysite.foo.urls')), - - # Uncomment the admin/doc line below to enable admin documentation: - # url(r'^admin/doc/', include('django.contrib.admindocs.urls')), - - # Uncomment the next line to enable the admin: - # url(r'^admin/', include(admin.site.urls)), + url(r'^polls/', include('polls.urls', namespace="polls")), + url(r'^admin/', include(admin.site.urls)), ) diff --git a/mysite/urls.pyc b/mysite/urls.pyc deleted file mode 100644 index 916e176..0000000 Binary files a/mysite/urls.pyc and /dev/null differ diff --git a/mysite/wsgi.pyc b/mysite/wsgi.pyc deleted file mode 100644 index a005e01..0000000 Binary files a/mysite/wsgi.pyc and /dev/null differ diff --git a/polls/__init__.pyc b/polls/__init__.pyc deleted file mode 100644 index 20c9239..0000000 Binary files a/polls/__init__.pyc and /dev/null differ diff --git a/polls/admin.py b/polls/admin.py new file mode 100644 index 0000000..e144212 --- /dev/null +++ b/polls/admin.py @@ -0,0 +1,23 @@ +from django.contrib import admin +from polls.models import Poll +from polls.models import Choice + +class ChoiceInline(admin.TabularInline): + model = Choice + extra = 3 + + +class PollAdmin(admin.ModelAdmin): + fieldsets = [ + (None, {'fields': ['question']}), + ('Date information', {'fields': ['pub_date'], 'classes': ['collapse']}), + ] + list_display = ('question', 'pub_date', 'was_published_recently') + list_filter = ['pub_date'] + search_fields = ['question'] + date_hierarchy = 'pub_date' + inlines = [ChoiceInline] + +admin.site.register(Poll, PollAdmin) + + diff --git a/polls/models.py b/polls/models.py index f8cc376..d1fdd01 100644 --- a/polls/models.py +++ b/polls/models.py @@ -10,7 +10,11 @@ def __unicode__(self): return self.question def was_published_recently(self): - return self.pub_date >= timezone.now() - datetime.timedelta(days=1) + now = timezone.now() + return now > self.pub_date >= now - datetime.timedelta(days=1) + was_published_recently.admin_order_field = 'pub_date' + was_published_recently.boolean = True + was_published_recently.short_description = 'Published recently?' class Choice(models.Model): diff --git a/polls/models.pyc b/polls/models.pyc deleted file mode 100644 index af237db..0000000 Binary files a/polls/models.pyc and /dev/null differ diff --git a/polls/templates/polls/detail.html b/polls/templates/polls/detail.html new file mode 100644 index 0000000..15da227 --- /dev/null +++ b/polls/templates/polls/detail.html @@ -0,0 +1,12 @@ +

{{ poll.question }}

+ +{% if error_message %}

{{ error_message }}

{% endif %} + +
+{% csrf_token %} +{% for choice in poll.choice_set.all %} + +
+{% endfor %} + +
diff --git a/polls/templates/polls/index.html b/polls/templates/polls/index.html new file mode 100644 index 0000000..4c15ce4 --- /dev/null +++ b/polls/templates/polls/index.html @@ -0,0 +1,9 @@ +{% if latest_poll_list %} + +{% else %} +

No polls are available.

+{% endif %} diff --git a/polls/templates/polls/results.html b/polls/templates/polls/results.html new file mode 100644 index 0000000..d6783ba --- /dev/null +++ b/polls/templates/polls/results.html @@ -0,0 +1,9 @@ +

{{ poll.question }}

+ + + +Vote again? diff --git a/polls/tests.py b/polls/tests.py index 501deb7..2baf66e 100644 --- a/polls/tests.py +++ b/polls/tests.py @@ -1,16 +1,32 @@ -""" -This file demonstrates writing tests using the unittest module. These will pass -when you run "manage.py test". - -Replace this with more appropriate tests for your application. -""" +import datetime +from django.utils import timezone from django.test import TestCase +from polls.models import Poll + +class PollMethodTests(TestCase): + + def test_was_published_recently_with_future_poll(self): + """ + was_published_recently() should return False for polls whose + pub_date is in the future + """ + future_poll = Poll(pub_date=timezone.now() + datetime.timedelta(days=30)) + self.assertEqual(future_poll.was_published_recently(), False) + + def test_was_published_recently_with_old_poll(self): + """ + was_published_recently() should return False for polls whose pub_date + is older than 1 day + """ + old_poll = Poll(pub_date=timezone.now() - datetime.timedelta(days=30)) + self.assertEqual(old_poll.was_published_recently(), False) -class SimpleTest(TestCase): - def test_basic_addition(self): + def test_was_published_recently_with_recent_poll(self): """ - Tests that 1 + 1 always equals 2. + was_published_recently() should return True for polls whose pub_date + is within the last day """ - self.assertEqual(1 + 1, 2) + recent_poll = Poll(pub_date=timezone.now() - datetime.timedelta(hours=1)) + self.assertEqual(recent_poll.was_published_recently(), True) diff --git a/polls/testsettings.py b/polls/testsettings.py new file mode 100644 index 0000000..b52b3f0 --- /dev/null +++ b/polls/testsettings.py @@ -0,0 +1,13 @@ +DATABASES = { + 'default': { + 'ENGINE': 'django.db.backends.sqlite3', + 'NAME': 'pollstests.db', + # The following settings are not used with sqlite3: + 'USER': '', + 'PASSWORD': '', + 'HOST': '', + 'PORT': '', + } +} + +SECRET_KEY = 'i4mth3m0sts3cr3t0f4lls3tti1ngs' diff --git a/polls/urls.py b/polls/urls.py new file mode 100644 index 0000000..3127d0b --- /dev/null +++ b/polls/urls.py @@ -0,0 +1,23 @@ +from django.conf.urls import patterns, url +from django.views.generic import DetailView, ListView +from polls.models import Poll + +urlpatterns = patterns('', + url(r'^$', + ListView.as_view( + queryset=Poll.objects.order_by('-pub_date')[:5], + context_object_name='latest_poll_list', + template_name='polls/index.html'), + name='index'), + url(r'^(?P\d+)/$', + DetailView.as_view( + model=Poll, + template_name='polls/detail.html'), + name='detail'), + url(r'^(?P\d+)/results/$', + DetailView.as_view( + model=Poll, + template_name='polls/results.html'), + name='results'), + url(r'^(?P\d+)/vote/$', 'polls.views.vote', name='vote'), +) diff --git a/polls/views.py b/polls/views.py index 60f00ef..bb42fc0 100644 --- a/polls/views.py +++ b/polls/views.py @@ -1 +1,27 @@ -# Create your views here. +from django.shortcuts import get_object_or_404, render +from django.http import HttpResponseRedirect +from django.core.urlresolvers import reverse +from polls.models import Choice, Poll + +def vote(request, poll_id): + p = get_object_or_404(Poll, pk=poll_id) + try: + selected_choice = p.choice_set.get(pk=request.POST['choice']) + except (KeyError, Choice.DoesNotExist): + # Redisplay the poll voting form. + return render(request, 'polls/detail.html', { + 'poll': p, + 'error_message': "You didn't select a choice.", + }) + else: + selected_choice.votes += 1 + selected_choice.save() + # Always return an HttpResponseRedirect after successfully dealing + # with POST data. This prevents data from being posted twice if a + # user hits the Back button. + return HttpResponseRedirect(reverse('polls:results', args=(p.id,))) + + +def results(request, poll_id): + poll = get_object_or_404(Poll, pk=poll_id) + return render(request, 'polls/results.html', {'poll': poll})