--- /dev/null
+from django.contrib import admin
+
+from models import Poll, PollItem
+
+
+class PollItemInline(admin.TabularInline):
+ model = PollItem
+ extra = 0
+ readonly_fields = ('vote_count',)
+
+
+class PollAdmin(admin.ModelAdmin):
+ inlines = [PollItemInline]
+
+
+class PollItemAdmin(admin.ModelAdmin):
+ readonly_fields = ('vote_count',)
+
+
+admin.site.register(Poll, PollAdmin)
+admin.site.register(PollItem, PollItemAdmin)
\ No newline at end of file
--- /dev/null
+from django import forms\r
+\r
+\r
+class PollForm(forms.Form):\r
+ vote = forms.ChoiceField(widget = forms.RadioSelect)\r
+ \r
+ def __init__(self, *args, **kwargs):
+ poll = kwargs.pop('poll', None)\r
+ super(PollForm, self).__init__(*args, **kwargs)\r
+ self.fields['vote'].choices = [(item.id, item.content) for item in poll.items.all()]
\ No newline at end of file
--- /dev/null
+# SOME DESCRIPTIVE TITLE.
+# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
+# This file is distributed under the same license as the PACKAGE package.
+# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
+#
+#, fuzzy
+msgid ""
+msgstr ""
+"Project-Id-Version: PACKAGE VERSION\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2013-05-20 14:04+0200\n"
+"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
+"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
+"Language-Team: LANGUAGE <LL@li.org>\n"
+"Language: \n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=3; plural=(n==1 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 "
+"|| n%100>=20) ? 1 : 2);\n"
+
+#: models.py:10
+msgid "Poll"
+msgstr "Ankieta"
+
+#: models.py:11
+msgid "Polls"
+msgstr "Ankiety"
+
+#: models.py:13
+msgid "question"
+msgstr "Pytanie"
+
+#: models.py:14
+msgid "slug"
+msgstr "slug"
+
+#: models.py:15
+msgid "open"
+msgstr "otwarta"
+
+#: models.py:19
+msgid "Slug of an open poll needs to be unique"
+msgstr "Slug otwartej ankiety musi być unikalny"
+
+#: models.py:36
+msgid "content"
+msgstr "treść"
+
+#: models.py:37
+msgid "vote count"
+msgstr "licznik głosów"
+
+#: models.py:40
+msgid "vote item"
+msgstr "Pozycja ankiety"
+
+#: models.py:41
+msgid "vote items"
+msgstr "Pozycje ankiety"
+
+#: templates/polls/poll.html:11
+msgid "Thanks for voting! You can see current results below."
+msgstr "Dziękujemy za oddanie głosu w ankiecie! Poniżej znajdują się bieżące wyniki."
+
+#: templates/polls/tags/poll.html:28
+msgid "Submit"
+msgstr "Wyślij"
--- /dev/null
+# -*- coding: utf-8 -*-
+import datetime
+from south.db import db
+from south.v2 import SchemaMigration
+from django.db import models
+
+
+class Migration(SchemaMigration):
+
+ def forwards(self, orm):
+ # Adding model 'Poll'
+ db.create_table(u'polls_poll', (
+ (u'id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
+ ('question', self.gf('django.db.models.fields.TextField')()),
+ ('slug', self.gf('django.db.models.fields.SlugField')(max_length=50)),
+ ('open', self.gf('django.db.models.fields.BooleanField')(default=False)),
+ ))
+ db.send_create_signal(u'polls', ['Poll'])
+
+ # Adding model 'PollItem'
+ db.create_table(u'polls_pollitem', (
+ (u'id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
+ ('poll', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['polls.Poll'])),
+ ('content', self.gf('django.db.models.fields.TextField')()),
+ ('vote_count', self.gf('django.db.models.fields.IntegerField')(default=0)),
+ ))
+ db.send_create_signal(u'polls', ['PollItem'])
+
+
+ def backwards(self, orm):
+ # Deleting model 'Poll'
+ db.delete_table(u'polls_poll')
+
+ # Deleting model 'PollItem'
+ db.delete_table(u'polls_pollitem')
+
+
+ models = {
+ u'polls.poll': {
+ 'Meta': {'object_name': 'Poll'},
+ u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'open': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+ 'question': ('django.db.models.fields.TextField', [], {}),
+ 'slug': ('django.db.models.fields.SlugField', [], {'max_length': '50'})
+ },
+ u'polls.pollitem': {
+ 'Meta': {'object_name': 'PollItem'},
+ 'content': ('django.db.models.fields.TextField', [], {}),
+ u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'poll': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['polls.Poll']"}),
+ 'vote_count': ('django.db.models.fields.IntegerField', [], {'default': '0'})
+ }
+ }
+
+ complete_apps = ['polls']
\ No newline at end of file
--- /dev/null
+from django.db import models
+from django.utils.translation import ugettext_lazy as _
+from django.core.exceptions import ValidationError
+from django.core.urlresolvers import reverse
+
+
+USED_POLLS_KEY = 'used_polls'
+
+
+class Poll(models.Model):
+
+ question = models.TextField(_('question'))
+ slug = models.SlugField(_('slug'))
+ open = models.BooleanField(_('open'), default = False)
+
+ class Meta:
+ verbose_name = _('Poll')
+ verbose_name_plural = _('Polls')
+
+ def clean(self):
+ if self.open and Poll.objects.exclude(pk = self.pk).filter(slug = self.slug).exists():
+ raise ValidationError(_('Slug of an open poll needs to be unique'))
+ return super(Poll, self).clean()
+
+ def __unicode__(self):
+ return self.question[:100] + ' (' + self.slug + ')'
+
+ def get_absolute_url(self):
+ return reverse('poll', args = [self.slug])
+
+ @property
+ def vote_count(self):
+ return self.items.all().aggregate(models.Sum('vote_count'))['vote_count__sum']
+
+ def voted(self, session):
+ return self.id in session.get(USED_POLLS_KEY, set())
+
+
+class PollItem(models.Model):
+
+ poll = models.ForeignKey(Poll, related_name = 'items')
+ content = models.TextField(_('content'))
+ vote_count = models.IntegerField(_('vote count'), default = 0)
+
+ class Meta:
+ verbose_name = _('vote item')
+ verbose_name_plural = _('vote items')
+ \r
+ def __unicode__(self):
+ return self.content + ' @ ' + unicode(self.poll)
+
+ @property
+ def vote_ratio(self):
+ return (float(self.vote_count) / self.poll.vote_count) * 100 if self.poll.vote_count else 0
+
+ def vote(self, session):
+ self.vote_count = self.vote_count + 1
+ self.save()
+ session.setdefault(USED_POLLS_KEY, set()).add(self.poll.id)
+ session.save()
\ No newline at end of file
--- /dev/null
+.poll{width:400px}.poll ul{list-style-type:none}.poll-bar{border:solid 1px #ddd;height:6px;margin-bottom:10px}.poll-bar-inner{background:orange;height:6px}.poll-msg{font-weight:bold}
\ No newline at end of file
--- /dev/null
+.poll {\r
+ width: 400px;\r
+ ul {\r
+ list-style-type: none;\r
+ }\r
+}\r
+\r
+.poll-bar {\r
+ border: solid 1px #ddd;\r
+ height:6px;\r
+ margin-bottom: 10px;\r
+}\r
+\r
+.poll-bar-inner {\r
+ background: orange;\r
+ height: 6px;\r
+}\r
+\r
+.poll-msg {\r
+ font-weight: bold;\r
+}
\ No newline at end of file
--- /dev/null
+{% extends "base.html" %}
+{% load i18n %}
+{% load polls_tags %}
+
+{% block titleextra %}{{poll.question}}{% endblock %}
+
+
+{% block body %}
+ <div class="normal-text">
+ {% if voted_already %}
+ <p class="poll-msg">{% trans "Thanks for voting! You can see current results below." %}</p>
+ {% endif %}
+ {% poll poll %}
+ </div>
+{% endblock %}
\ No newline at end of file
--- /dev/null
+{% load i18n %}
+
+{% if poll %}
+ {% if voted_already %}
+ {% if show_results %}
+ <div class="poll">
+ <p>{{poll.question}}</p>
+ <ul>
+ {% for item in poll.items.all %}
+ <li>
+ {{item.content}}
+ <div class="poll-bar"><div class="poll-bar-inner"
+ {% if vote_count %}
+ style="width:{{item.vote_ratio|stringformat:"f"}}%;"
+ {% endif %}
+ ></div></div>
+ </li>
+ {% endfor %}
+ </ul>
+ </div>
+ {% endif %}
+ {% else %}
+ <div class="poll">
+ <p>{{poll.question}}</p>
+ <form action="{{poll.get_absolute_url}}" method="post">{% csrf_token %}
+ {{ form.vote }}
+ <input type="submit" value="{% trans "Submit" %}" />
+ </form>
+ </div>
+ {% endif %}
+{% endif %}
\ No newline at end of file
--- /dev/null
+from django import template
+from ..forms import PollForm
+
+
+register = template.Library()
+
+@register.inclusion_tag('polls/tags/poll.html', takes_context = True)
+def poll(context, poll, show_results = True, redirect_to = ''):
+ form = None
+ voted_already = poll.voted(context.get('request').session)
+ if not voted_already:
+ form = PollForm(poll = poll, initial = dict(redirect_to = redirect_to))
+ return dict(poll = poll,
+ form = form,
+ voted_already = voted_already,
+ vote_count = poll.vote_count,
+ show_results = show_results
+ )
\ No newline at end of file
--- /dev/null
+from django.conf.urls import patterns, url, include
+
+
+urlpatterns = patterns('polls.views',
+ url(r'^(?P<slug>[^/]+)$', 'poll', name='poll'),
+)
--- /dev/null
+from django.views.decorators.http import require_http_methods\r
+from django.shortcuts import get_object_or_404, redirect, render_to_response\r
+from django.core.urlresolvers import reverse\r
+from django.template import RequestContext
+
+from models import Poll, PollItem\r
+from forms import PollForm
+
+\r
+@require_http_methods(['GET', 'POST'])\r
+def poll(request, slug):
+
+ poll = get_object_or_404(Poll, slug = slug)
+
+ if request.method == 'POST':\r
+ redirect_to = reverse('poll', args = [slug])
+ form = PollForm(request.POST, poll = poll)\r
+ if form.is_valid():\r
+ if not poll.voted(request.session):\r
+ try:\r
+ poll_item = PollItem.objects.filter(pk = form.cleaned_data['vote'], poll = poll).get()
+ except PollItem.DoesNotExist:\r
+ pass\r
+ else:\r
+ poll_item.vote(request.session)
+ return redirect(redirect_to)
+ elif request.method == 'GET':
+ context = RequestContext(request)
+ context['poll'] = poll\r
+ context['voted_already'] = poll.voted(request.session)
+ return render_to_response('polls/poll.html', context)
+
+ \r
+
\ No newline at end of file
'search',
'oai',
'funding',
+ 'polls'
]
GETPAID_BACKENDS = (
'sponsors/css/sponsors.css',
'css/auth.css',
'funding/funding.scss',
+ 'polls/polls.scss',
'css/form.scss',
'css/social/shelf_tags.css',
url(r'^uzytkownik/', include('allauth.urls')),
url(r'^czekaj/', include('waiter.urls')),
url(r'^wesprzyj/', include('funding.urls')),
+ url(r'^ankieta/', include('polls.urls')),
# Admin panel
url(r'^admin/catalogue/book/import$', 'catalogue.views.import_book', name='import_book'),