--- /dev/null
+localsettings.py
+*.db
+*.db-journal
+*~
+
+# Python garbage
+*.pyc
+.coverage
+pip-log.txt
+nosetests.xml
+
+# Mac OS X garbage
+.DS_Store
+
+# Windows garbage
+thumbs.db
+
+# Eclipse
+.project
+.settings
+.pydevproject
+.tmp_*
+
--- /dev/null
+=========
+KOED Quiz
+=========
+
+This project will be used for various openness related tests and quizzes.
--- /dev/null
+from django.contrib import admin
+
+from quiz.models import Question, Result, Answer
+
+
+class AnswerInline(admin.TabularInline):
+ model = Answer
+ fk_name = 'question'
+ extra = 2
+
+
+class QuestionAdmin(admin.ModelAdmin):
+ inlines = [AnswerInline]
+ list_display = ['title', 'quiz']
+
+
+admin.site.register(Question, QuestionAdmin)
+admin.site.register(Result)
--- /dev/null
+from django import forms
+from django.forms.widgets import RadioSelect
+from django.utils.translation import ugettext_lazy as _
+from quiz.models import Answer
+
+class QuestionForm(forms.Form):
+ answer = forms.ModelChoiceField(widget=RadioSelect,
+ queryset=Answer.objects.all(), empty_label=None,
+ error_messages={'required': _('Please select an option')})
+
+ def __init__(self, instance, *args, **kwargs):
+ r = super(QuestionForm, self).__init__(*args, **kwargs)
+ self.fields['answer'].queryset = instance.answer_set.all()
+ return r
--- /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.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: Quiz 0.1\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2011-09-20 17:10+0200\n"
+"PO-Revision-Date: 2011-09-20 17:10+0100\n"
+"Last-Translator: Radek Czajka <radoslaw.czajka@nowoczesnapolska.org.pl>\n"
+"Language-Team: LANGUAGE <LL@li.org>\n"
+"Language: pl\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"
+
+#: forms.py:9
+msgid "Please select an option"
+msgstr "Proszę wybrać jedną z odpowiedzi"
+
+#: models.py:11
+msgid "quiz"
+msgstr "quiz"
+
+#: models.py:12
+msgid "quizzes"
+msgstr "quizy"
+
+#: models.py:40
+msgid "result"
+msgstr "rezultat"
+
+#: models.py:41
+msgid "results"
+msgstr "rezultaty"
+
+#: models.py:60
+msgid "question"
+msgstr "pytanie"
+
+#: models.py:61
+msgid "questions"
+msgstr "pytania"
+
+#: models.py:90
+msgid "answer"
+msgstr "odpowiedź"
+
+#: models.py:91
+msgid "answers"
+msgstr "odpowiedzi"
+
+#: templates/quiz/question_detail.html:26 templates/quiz/result_detail.html:20
+msgid "Back to last question"
+msgstr "Wróć do poprzedniego pytania"
+
+#: templates/quiz/question_detail.html:31 templates/quiz/result_detail.html:24
+msgid "Back to my test"
+msgstr "Wróć do testu"
+
+#: templates/quiz/question_detail.html:33 templates/quiz/result_detail.html:26
+msgid "Start from the beginning"
+msgstr "Zacznij od początku"
+
+#: templates/quiz/result_detail.html:32
+msgid "Start again"
+msgstr "Jeszcze raz od początku"
--- /dev/null
+# encoding: 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 'Result'
+ db.create_table('quiz_result', (
+ ('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
+ ('quiz', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['sites.Site'])),
+ ('slug', self.gf('django.db.models.fields.SlugField')(max_length=50, db_index=True)),
+ ('title', self.gf('django.db.models.fields.CharField')(max_length=255)),
+ ('text', self.gf('django.db.models.fields.TextField')()),
+ ))
+ db.send_create_signal('quiz', ['Result'])
+
+ # Adding model 'Question'
+ db.create_table('quiz_question', (
+ ('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
+ ('quiz', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['sites.Site'])),
+ ('slug', self.gf('django.db.models.fields.SlugField')(max_length=50, db_index=True)),
+ ('ordering', self.gf('django.db.models.fields.SmallIntegerField')()),
+ ('title', self.gf('django.db.models.fields.CharField')(max_length=255)),
+ ('text', self.gf('django.db.models.fields.TextField')(null=True, blank=True)),
+ ('description', self.gf('django.db.models.fields.TextField')(null=True, blank=True)),
+ ))
+ db.send_create_signal('quiz', ['Question'])
+
+ # Adding unique constraint on 'Question', fields ['quiz', 'slug']
+ db.create_unique('quiz_question', ['quiz_id', 'slug'])
+
+ # Adding unique constraint on 'Question', fields ['quiz', 'ordering']
+ db.create_unique('quiz_question', ['quiz_id', 'ordering'])
+
+ # Adding model 'Answer'
+ db.create_table('quiz_answer', (
+ ('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
+ ('title', self.gf('django.db.models.fields.CharField')(max_length=255)),
+ ('question', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['quiz.Question'])),
+ ('go_to', self.gf('django.db.models.fields.related.ForeignKey')(blank=True, related_name='go_tos', null=True, to=orm['quiz.Question'])),
+ ('result', self.gf('django.db.models.fields.related.ForeignKey')(to=orm['quiz.Result'], null=True, blank=True)),
+ ('ordering', self.gf('django.db.models.fields.SmallIntegerField')()),
+ ))
+ db.send_create_signal('quiz', ['Answer'])
+
+
+ def backwards(self, orm):
+
+ # Removing unique constraint on 'Question', fields ['quiz', 'ordering']
+ db.delete_unique('quiz_question', ['quiz_id', 'ordering'])
+
+ # Removing unique constraint on 'Question', fields ['quiz', 'slug']
+ db.delete_unique('quiz_question', ['quiz_id', 'slug'])
+
+ # Deleting model 'Result'
+ db.delete_table('quiz_result')
+
+ # Deleting model 'Question'
+ db.delete_table('quiz_question')
+
+ # Deleting model 'Answer'
+ db.delete_table('quiz_answer')
+
+
+ models = {
+ 'quiz.answer': {
+ 'Meta': {'ordering': "['question', 'ordering']", 'object_name': 'Answer'},
+ 'go_to': ('django.db.models.fields.related.ForeignKey', [], {'blank': 'True', 'related_name': "'go_tos'", 'null': 'True', 'to': "orm['quiz.Question']"}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'ordering': ('django.db.models.fields.SmallIntegerField', [], {}),
+ 'question': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['quiz.Question']"}),
+ 'result': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['quiz.Result']", 'null': 'True', 'blank': 'True'}),
+ 'title': ('django.db.models.fields.CharField', [], {'max_length': '255'})
+ },
+ 'quiz.question': {
+ 'Meta': {'ordering': "['quiz', 'ordering']", 'unique_together': "[['quiz', 'slug'], ['quiz', 'ordering']]", 'object_name': 'Question'},
+ 'description': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'ordering': ('django.db.models.fields.SmallIntegerField', [], {}),
+ 'quiz': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['sites.Site']"}),
+ 'slug': ('django.db.models.fields.SlugField', [], {'max_length': '50', 'db_index': 'True'}),
+ 'text': ('django.db.models.fields.TextField', [], {'null': 'True', 'blank': 'True'}),
+ 'title': ('django.db.models.fields.CharField', [], {'max_length': '255'})
+ },
+ 'quiz.quiz': {
+ 'Meta': {'ordering': "('domain',)", 'object_name': 'Quiz', 'db_table': "'django_site'", '_ormbases': ['sites.Site'], 'proxy': 'True'}
+ },
+ 'quiz.result': {
+ 'Meta': {'object_name': 'Result'},
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'quiz': ('django.db.models.fields.related.ForeignKey', [], {'to': "orm['sites.Site']"}),
+ 'slug': ('django.db.models.fields.SlugField', [], {'max_length': '50', 'db_index': 'True'}),
+ 'text': ('django.db.models.fields.TextField', [], {}),
+ 'title': ('django.db.models.fields.CharField', [], {'max_length': '255'})
+ },
+ 'sites.site': {
+ 'Meta': {'ordering': "('domain',)", 'object_name': 'Site', 'db_table': "'django_site'"},
+ 'domain': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'name': ('django.db.models.fields.CharField', [], {'max_length': '50'})
+ }
+ }
+
+ complete_apps = ['quiz']
--- /dev/null
+from django.db import models
+from django.contrib.sites.models import Site
+from django.utils.translation import ugettext_lazy as _
+
+from django.conf import settings
+
+
+class Quiz(Site):
+ class Meta:
+ proxy=True
+ verbose_name = _('quiz')
+ verbose_name_plural = _('quizzes')
+
+ @classmethod
+ def current(cls):
+ return cls.objects.get(id=settings.SITE_ID)
+
+ def start(self):
+ return self.question_set.all()[0]
+
+ @models.permalink
+ def get_absolute_url(self):
+ return ('quiz', )
+
+ def where_to(self):
+ try:
+ return Result.objects.get(quiz=self).get_absolute_url()
+ except Result.DoesNotExist:
+ # just go to the beginning
+ return self.get_absolute_url()
+
+
+class Result(models.Model):
+ quiz = models.ForeignKey(Quiz)
+ slug = models.SlugField(db_index=True)
+ title = models.CharField(max_length=255)
+ text = models.TextField()
+
+ class Meta:
+ verbose_name = _('result')
+ verbose_name_plural = _('results')
+
+ def __unicode__(self):
+ return self.title
+
+ @models.permalink
+ def get_absolute_url(self):
+ return ('quiz_result', [self.slug])
+
+
+class Question(models.Model):
+ quiz = models.ForeignKey(Quiz)
+ slug = models.SlugField(db_index=True)
+ ordering = models.SmallIntegerField()
+ title = models.CharField(max_length=255)
+ text = models.TextField(null=True, blank=True)
+ description = models.TextField(null=True, blank=True)
+
+ class Meta:
+ verbose_name = _('question')
+ verbose_name_plural = _('questions')
+ ordering = ['quiz', 'ordering']
+ unique_together = [['quiz', 'slug'], ['quiz', 'ordering']]
+
+ def __unicode__(self):
+ return self.title
+
+ @models.permalink
+ def get_absolute_url(self):
+ return ('quiz', [self.slug])
+
+ def where_to(self):
+ later = self.quiz.question_set.filter(ordering__gt=self.ordering)
+ if later.exists():
+ return later[0].get_absolute_url()
+ else:
+ return self.quiz.where_to()
+
+
+
+class Answer(models.Model):
+ title = models.CharField(max_length=255)
+ question = models.ForeignKey(Question)
+ go_to = models.ForeignKey(Question, null=True, blank=True,
+ related_name='go_tos')
+ result = models.ForeignKey(Result, null=True, blank=True)
+ ordering = models.SmallIntegerField()
+
+ class Meta:
+ verbose_name = _('answer')
+ verbose_name_plural = _('answers')
+ ordering = ['question', 'ordering']
+
+ def __unicode__(self):
+ return self.title
+
+ def where_to(self):
+ # follow explicit redirects
+ if self.result:
+ return self.result.get_absolute_url()
+ elif self.go_to:
+ return self.go_to.get_absolute_url()
+
+ # or just get the next question
+ return self.question.where_to()
--- /dev/null
+{% extends "base.html" %}
+{% load i18n %}
+{% load url from future %}
+
+{% block "body" %}
+
+
+<h1>{{ question.title }}</h1>
+<div>
+{{ question.text }}
+</div>
+
+<div>
+
+
+
+<form method='post'>
+{% csrf_token %}
+{{ form.answer.errors }}
+{{ form.answer }}
+
+{% if valid %}
+ <input type='submit' />
+
+ {% if previous_url %}
+ <a href='{{ previous_url }}'>{% trans "Back to last question" %}</a>
+ {% endif %}
+
+{% else %}
+ {% if valid_url %}
+ <a href='{{ valid_url }}'>{% trans "Back to my test" %}</a>
+ {% else %}
+ <a href='{% url "quiz" %}'>{% trans "Start from the beginning" %}</a>
+ {% endif %}
+{% endif %}
+
+</form>
+</div>
+
+
+<div>
+{{ question.description }}
+</div>
+
+
+{% endblock %}
--- /dev/null
+{% extends "base.html" %}
+{% load i18n %}
+{% load url from future %}
+
+
+{% block "body" %}
+
+<h1>{{ result.title }}</h1>
+
+
+
+<div>
+{{ result.text }}
+</div>
+
+
+
+{% if valid %}
+ {% if previous_url %}
+ <a href='{{ previous_url }}'>{% trans "Back to last question" %}</a>
+ {% endif %}
+{% else %}
+ {% if valid_url %}
+ <a href='{{ valid_url }}'>{% trans "Back to my test" %}</a>
+ {% else %}
+ <a href='{% url "quiz" %}'>{% trans "Start from the beginning" %}</a>
+ {% endif %}
+{% endif %}
+
+
+
+<a href='{% url "quiz" %}'>{% trans "Start again" %}</a>
+
+{% endblock %}
--- /dev/null
+from django.conf.urls.defaults import *
+
+
+urlpatterns = patterns('quiz.views',
+ url(r'^$', 'question', name='quiz'),
+ url(r'^q/(?P<slug>[-a-z0-9]*)/$', 'question', name='quiz'),
+ url(r'^r/(?P<slug>[-a-z0-9]*)/$', 'result', name='quiz_result'),
+)
--- /dev/null
+from django.shortcuts import get_object_or_404, render, redirect
+
+from quiz.forms import QuestionForm
+from quiz.models import Quiz
+
+
+def question(request, slug=None):
+ if slug is None:
+ question = Quiz.current().start()
+ request.session['ticket'] = [request.path]
+ else:
+ question = get_object_or_404(Quiz.current().question_set, slug=slug)
+
+ ticket = request.session.get('ticket')
+ valid = request.path in ticket
+ print ticket, valid
+ if valid:
+ cur_index = ticket.index(request.path)
+ if cur_index:
+ previous_url = ticket[cur_index - 1]
+ else:
+ valid_url = ticket[-1]
+
+ if request.method == 'POST' and valid:
+ form = QuestionForm(question, request.POST)
+ if form.is_valid():
+
+ answer = form.cleaned_data['answer']
+ where_to = answer.where_to()
+
+ del ticket[cur_index + 1:]
+ try:
+ del ticket[ticket.index(where_to) + 1:]
+ except ValueError:
+ ticket.append(where_to)
+
+ request.session['ticket'] = ticket
+
+ return redirect(where_to)
+ else:
+ form = QuestionForm(question)
+
+ return render(request, "quiz/question_detail.html", locals())
+
+
+def result(request, slug=None):
+ ticket = request.session['ticket']
+ valid = request.path in ticket
+
+ result = get_object_or_404(Quiz.current().result_set, slug=slug)
+ return render(request, "quiz/result_detail.html", locals())
+
--- /dev/null
+from __future__ import with_statement # needed for python 2.5
+from fabric.api import *
+from fabric.contrib import files
+
+import os
+
+
+# ==========
+# = Config =
+# ==========
+# Globals
+env.project_name = 'koedquiz'
+env.use_south = True
+
+# Servers
+def localhost():
+ """SSH to localhost (for debugging).
+
+ This will deploy to `test-deployment` in the project dir.
+
+ """
+ import os.path
+ from getpass import getuser
+
+ env.hosts = ['localhost']
+ env.user = getuser()
+ env.path = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'test-deployment')
+ env.virtualenv = '/usr/bin/virtualenv'
+ # This goes to VHost configuration
+ env.server_name = 'koedquiz.example.com'
+ env.server_admin = 'koedquiz <koedquiz@koedquiz.example.com>'
+ # /var/log/apache2/* logs
+ env.access_log = 'koedquiz.log'
+ env.error_log = 'koedquiz-errors.log'
+
+
+# add additional servers here
+
+
+servers = [localhost]
+
+# =========
+# = Tasks =
+# =========
+def test():
+ "Run the test suite and bail out if it fails"
+ require('hosts', 'path', provided_by=servers)
+ require('python', provided_by=[find_python])
+ result = run('cd %(path)s/%(project_name)s; %(python)s manage.py test' % env)
+
+def setup():
+ """
+ Setup a fresh virtualenv as well as a few useful directories, then run
+ a full deployment. virtualenv with pip should be already installed.
+ """
+ require('hosts', 'path', 'virtualenv', provided_by=servers)
+
+ run('mkdir -p %(path)s; cd %(path)s; %(virtualenv)s ve;' % env, pty=True)
+ run('cd %(path)s; mkdir releases; mkdir packages;' % env, pty=True)
+ run('cd %(path)s/releases; ln -s . current; ln -s . previous' % env, pty=True)
+ upload_default_localsettings()
+ deploy()
+
+def deploy():
+ """
+ Deploy the latest version of the site to the servers,
+ install any required third party modules,
+ install the virtual host and then restart the webserver
+ """
+
+ import time
+ env.release = time.strftime('%Y-%m-%dT%H%M')
+
+ upload_tar_from_git()
+ find_python()
+ upload_wsgi_script()
+ upload_vhost_sample()
+ install_requirements()
+ copy_localsettings()
+ symlink_current_release()
+ collectstatic()
+ migrate()
+ restart_webserver()
+
+def deploy_version(version):
+ "Specify a specific version to be made live"
+ require('hosts', 'path', provided_by=servers)
+ env.version = version
+ with cd(env.path):
+ run('rm releases/previous; mv releases/current releases/previous;', pty=True)
+ run('ln -s %(version)s releases/current' % env, pty=True)
+ restart_webserver()
+
+def rollback():
+ """
+ Limited rollback capability. Simple loads the previously current
+ version of the code. Rolling back again will swap between the two.
+ """
+ require('hosts', 'path', provided_by=servers)
+ with cd(env.path):
+ run('mv releases/current releases/_previous;', pty=True)
+ run('mv releases/previous releases/current;', pty=True)
+ run('mv releases/_previous releases/previous;', pty=True)
+ restart_webserver()
+
+
+# =====================================================================
+# = Helpers. These are called by other functions rather than directly =
+# =====================================================================
+def upload_tar_from_git():
+ "Create an archive from the current Git branch and upload it"
+ print '>>> upload tar from git'
+ require('path', provided_by=servers)
+ require('release', provided_by=[deploy])
+ local('/bin/bash lib/git-archive-all.sh --format tar %(release)s.tar' % env)
+ local('gzip %(release)s.tar' % env)
+ run('mkdir -p %(path)s/releases/%(release)s' % env, pty=True)
+ run('mkdir -p %(path)s/packages' % env, pty=True)
+ put('%(release)s.tar.gz' % env, '%(path)s/packages/' % env)
+ run('cd %(path)s/releases/%(release)s && tar zxf ../../packages/%(release)s.tar.gz' % env, pty=True)
+ local('rm %(release)s.tar.gz' % env)
+
+def find_python():
+ "Finds where virtualenv Python stuff is"
+ print ">>> find Python paths"
+ require('path', provided_by=servers)
+ env.python = '%(path)s/ve/bin/python' % env
+ env.pip = '%(path)s/ve/bin/pip' % env
+ env.site_packages = run('%(python)s -c "from distutils.sysconfig import get_python_lib; print get_python_lib()"' % env)
+
+def upload_vhost_sample():
+ "Create and upload Apache virtual host configuration sample"
+ print ">>> upload vhost sample"
+ require('path', 'project_name', 'user', provided_by=servers)
+ require('access_log', 'error_log', 'server_admin', 'server_name', provided_by=servers)
+ require('site_packages', provided_by=[find_python])
+ files.upload_template('%(project_name)s.vhost.template' % env, '%(path)s/%(project_name)s.vhost' % env, context=env)
+
+def upload_wsgi_script():
+ "Create and upload a wsgi script sample"
+ print ">>> upload wsgi script sample"
+ require('path', 'project_name', provided_by=servers)
+ require('python', 'site_packages', provided_by=[find_python])
+ files.upload_template('%(project_name)s.wsgi.template' % env, '%(path)s/%(project_name)s.wsgi' % env, context=env)
+ run('chmod ug+x %(path)s/%(project_name)s.wsgi' % env)
+
+def install_requirements():
+ "Install the required packages from the requirements file using pip"
+ print '>>> install requirements'
+ require('path', provided_by=servers)
+ require('release', provided_by=[deploy])
+ require('pip', provided_by=[find_python])
+ run('%(pip)s install -r %(path)s/releases/%(release)s/requirements.txt' % env, pty=True)
+
+def secret_key():
+ """Generates a new SECRET_KEY."""
+ from random import Random
+ import string
+
+ r = Random()
+ return "".join(r.choice(string.printable) for i in range(64))
+
+def upload_default_localsettings():
+ "Uploads localsettings.py with media paths and stuff"
+ print ">>> upload default localsettings.py"
+ require('path', provided_by=servers)
+
+ env.secret_key = secret_key()
+ files.upload_template('%(project_name)s/localsettings.py.template' % env, '%(path)s/localsettings.py' % env, context=env)
+
+def copy_localsettings():
+ "Copy localsettings.py from root directory to release directory (if this file exists)"
+ print ">>> copy localsettings"
+ require('path', 'project_name', provided_by=servers)
+ require('release', provided_by=[deploy])
+
+ with settings(warn_only=True):
+ run('cp %(path)s/localsettings.py %(path)s/releases/%(release)s/%(project_name)s' % env)
+
+def symlink_current_release():
+ "Symlink our current release"
+ print '>>> symlink current release'
+ require('path', provided_by=servers)
+ require('release', provided_by=[deploy])
+ with cd(env.path):
+ run('rm releases/previous; mv releases/current releases/previous')
+ run('ln -s %(release)s releases/current' % env)
+
+def collectstatic():
+ """Runs collectstatic management command from Django staticfiles."""
+ print '>>> collectstatic'
+ require('path', 'project_name', provided_by=servers)
+ require('python', provided_by=[find_python])
+ with cd('%(path)s/releases/current/%(project_name)s' % env):
+ run('%(python)s manage.py collectstatic --noinput' % env, pty=True)
+
+def migrate():
+ "Update the database"
+ print '>>> migrate'
+ require('path', 'project_name', provided_by=servers)
+ require('python', provided_by=[find_python])
+ with cd('%(path)s/releases/current/%(project_name)s' % env):
+ run('%(python)s manage.py syncdb --noinput' % env, pty=True)
+ if env.use_south:
+ run('%(python)s manage.py migrate' % env, pty=True)
+
+def restart_webserver():
+ "Restart the web server"
+ print '>>> restart webserver'
+ require('path', 'project_name', provided_by=servers)
+ run('touch %(path)s/%(project_name)s.wsgi' % env)
--- /dev/null
+<VirtualHost *:80>
+ ServerName "%(server_name)s"
+ ServerAdmin "%(server_admin)s"
+
+ WSGIDaemonProcess %(project_name)s user=%(user)s group=%(user)s processes=2 threads=15 display-name=%%{GROUP} python-path=%(site_packages)s
+ WSGIProcessGroup %(project_name)s
+
+ WSGIScriptAlias / %(path)s/%(project_name)s.wsgi
+ <Directory %(path)s>
+ Order allow,deny
+ allow from all
+ </Directory>
+
+ Alias /media %(path)s/media
+ <Directory %(path)s/media>
+ Options Indexes
+ Order allow,deny
+ Allow from all
+ </Directory>
+
+ Alias /static %(path)s/releases/current/%(project_name)s/static
+ <Directory %(path)s/releases/current/%(project_name)s/static>
+ Options Indexes
+ Order allow,deny
+ Allow from all
+ </Directory>
+
+ LogLevel warn
+ ErrorLog /var/log/apache2/%(error_log)s
+ CustomLog /var/log/apache2/%(access_log)s combined
+</VirtualHost>
--- /dev/null
+#!%(python)s
+import site
+site.addsitedir('%(site_packages)s')
+
+import os
+from os.path import abspath, dirname, join
+import sys
+
+# Redirect sys.stdout to sys.stderr for bad libraries like geopy that use
+# print statements for optional import exceptions.
+sys.stdout = sys.stderr
+
+# Add apps and lib directories to PYTHONPATH
+sys.path = [
+ '%(path)s/releases/current/%(project_name)s',
+ '%(path)s/releases/current',
+ '%(path)s/releases/current/apps',
+ '%(path)s/releases/current/lib',
+ # add paths to submodules here
+] + sys.path
+
+# Run Django
+os.environ['DJANGO_SETTINGS_MODULE'] = 'settings'
+
+from django.core.handlers.wsgi import WSGIHandler
+application = WSGIHandler()
--- /dev/null
+# This template is uploaded by `fab setup`.
+# You should fill out the details in the version deployed on the server.
+
+
+ADMINS = (
+ #('Name', 'E-mail'),
+)
+
+MANAGERS = (
+ #('Name', 'E-mail'),
+)
+
+# on
+DATABASES = {
+ 'default': {
+ 'ENGINE': 'django.db.backends.', # Add 'postgresql_psycopg2', 'postgresql', 'mysql', 'sqlite3' or 'oracle'.
+ 'NAME': '', # Or path to database file if using sqlite3.
+ 'USER': '', # Not used with sqlite3.
+ 'PASSWORD': '', # Not used with sqlite3.
+ 'HOST': '', # Set to empty string for localhost. Not used with sqlite3.
+ 'PORT': '', # Set to empty string for default. Not used with sqlite3.
+ }
+}
+
+
+SECRET_KEY = %(secret_key)r
+MEDIA_ROOT = '%(path)s/media/'
--- /dev/null
+#!/usr/bin/env python
+import os.path
+import sys
+
+ROOT = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
+
+# Add apps and lib directories to PYTHONPATH
+sys.path = [
+ os.path.join(ROOT, 'apps'),
+ os.path.join(ROOT, 'lib'),
+ # add /lib/* paths here for submodules
+] + sys.path
+
+from django.core.management import execute_manager
+import imp
+try:
+ imp.find_module('settings') # Assumed to be in the same directory.
+except ImportError:
+ import sys
+ sys.stderr.write("Error: Can't find the file 'settings.py' in the directory containing %r. It appears you've customized things.\nYou'll have to run django-admin.py, passing it your settings module.\n" % __file__)
+ sys.exit(1)
+
+import settings
+
+if __name__ == "__main__":
+ execute_manager(settings)
--- /dev/null
+# -*- coding: utf-8 -*-
+# Django settings for koedquiz project.
+import os.path
+
+PROJECT_DIR = os.path.abspath(os.path.dirname(__file__))
+
+DEBUG = False
+TEMPLATE_DEBUG = DEBUG
+
+ADMINS = [
+ # ('Your Name', 'your_email@domain.com'),
+]
+
+MANAGERS = ADMINS
+
+DATABASES = {
+ 'default': {
+ 'ENGINE': 'django.db.backends.sqlite3', # Add 'postgresql_psycopg2', 'postgresql', 'mysql', 'sqlite3' or 'oracle'.
+ 'NAME': os.path.join(PROJECT_DIR, 'dev.db'), # Or path to database file if using sqlite3.
+ 'USER': '', # Not used with sqlite3.
+ 'PASSWORD': '', # Not used with sqlite3.
+ 'HOST': '', # Set to empty string for localhost. Not used with sqlite3.
+ 'PORT': '', # Set to empty string for default. Not used with sqlite3.
+ }
+}
+
+# Local time zone for this installation. Choices can be found here:
+# http://en.wikipedia.org/wiki/List_of_tz_zones_by_name
+# although not all choices may be available on all operating systems.
+# On Unix systems, a value of None will cause Django to use the same
+# timezone as the operating system.
+# If running in a Windows environment this must be set to the same as your
+# system time zone.
+TIME_ZONE = None
+
+# Language code for this installation. All choices can be found here:
+# http://www.i18nguy.com/unicode/language-identifiers.html
+LANGUAGE_CODE = 'pl'
+
+SITE_ID = 1
+
+# If you set this to False, Django will make some optimizations so as not
+# to load the internationalization machinery.
+USE_I18N = True
+
+# If you set this to False, Django will not format dates, numbers and
+# calendars according to the current locale
+USE_L10N = True
+
+# Absolute filesystem path to the directory that will hold user-uploaded files.
+# Example: "/home/media/media.lawrence.com/media/"
+MEDIA_ROOT = os.path.join(PROJECT_DIR, '../media')
+
+# URL that handles the media served from MEDIA_ROOT. Make sure to use a
+# trailing slash.
+# Examples: "http://media.lawrence.com/media/", "http://example.com/media/"
+MEDIA_URL = '/media/'
+
+# Absolute path to the directory static files should be collected to.
+# Don't put anything in this directory yourself; store your static files
+# in apps' "static/" subdirectories and in STATICFILES_DIRS.
+# Example: "/home/media/media.lawrence.com/static/"
+STATIC_ROOT = os.path.join(PROJECT_DIR, '../static')
+
+# URL prefix for static files.
+# Example: "http://media.lawrence.com/static/"
+STATIC_URL = '/static/'
+
+# URL prefix for admin static files -- CSS, JavaScript and images.
+# Make sure to use a trailing slash.
+# Examples: "http://foo.com/static/admin/", "/static/admin/".
+ADMIN_MEDIA_PREFIX = '/static/admin/'
+
+# Additional locations of static files
+STATICFILES_DIRS = (
+ # Put strings here, like "/home/html/static" or "C:/www/django/static".
+ # Always use forward slashes, even on Windows.
+ # Don't forget to use absolute paths, not relative paths.
+)
+
+# List of finder classes that know how to find static files in
+# various locations.
+STATICFILES_FINDERS = (
+ 'django.contrib.staticfiles.finders.FileSystemFinder',
+ 'django.contrib.staticfiles.finders.AppDirectoriesFinder',
+# 'django.contrib.staticfiles.finders.DefaultStorageFinder',
+)
+
+# List of callables that know how to import templates from various sources.
+TEMPLATE_LOADERS = [
+ 'django.template.loaders.filesystem.Loader',
+ 'django.template.loaders.app_directories.Loader',
+# 'django.template.loaders.eggs.Loader',
+]
+
+MIDDLEWARE_CLASSES = [
+ 'django.middleware.common.CommonMiddleware',
+ 'django.contrib.sessions.middleware.SessionMiddleware',
+ 'django.middleware.csrf.CsrfViewMiddleware',
+ 'django.contrib.auth.middleware.AuthenticationMiddleware',
+ 'django.contrib.messages.middleware.MessageMiddleware',
+]
+
+ROOT_URLCONF = 'koedquiz.urls'
+
+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.
+ os.path.join(PROJECT_DIR, 'templates'),
+]
+
+INSTALLED_APPS = [
+ 'django.contrib.auth',
+ 'django.contrib.contenttypes',
+ 'django.contrib.sessions',
+ 'django.contrib.sites',
+ 'django.contrib.messages',
+ 'django.contrib.staticfiles',
+
+ 'django.contrib.admin',
+ 'django.contrib.admindocs',
+
+ 'south',
+
+ 'quiz',
+]
+
+# A sample logging configuration. The only tangible logging
+# performed by this configuration is to send an email to
+# the site admins on every HTTP 500 error.
+# See http://docs.djangoproject.com/en/dev/topics/logging for
+# more details on how to customize your logging configuration.
+LOGGING = {
+ 'version': 1,
+ 'disable_existing_loggers': False,
+ 'handlers': {
+ 'mail_admins': {
+ 'level': 'ERROR',
+ 'class': 'django.utils.log.AdminEmailHandler'
+ }
+ },
+ 'loggers': {
+ 'django.request': {
+ 'handlers': ['mail_admins'],
+ 'level': 'ERROR',
+ 'propagate': True,
+ },
+ }
+}
+
+# Load localsettings, if they exist
+try:
+ from localsettings import *
+except ImportError:
+ pass
--- /dev/null
+<!DOCTYPE HTML>
+<html>
+
+<head>
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
+ <title>{% block "title" %}{% endblock %}</title>
+</head>
+
+<body>
+ {% block "body" %}{% endblock %}
+</body>
+
+</html>
--- /dev/null
+{% extends "base.html" %}
+
+{% block "body" %}
+
+<a href="{{ quiz.get_absolute_url }}">Start quiz!</a>
+
+{% endblock %}
--- /dev/null
+from django.conf.urls.defaults import patterns, include, url
+
+from django.contrib import admin
+admin.autodiscover()
+
+urlpatterns = patterns('',
+ url(r'^$', 'koedquiz.views.home', name='main_page'),
+
+ url(r'^quiz/', include('quiz.urls')),
+
+ url(r'^admin/doc/', include('django.contrib.admindocs.urls')),
+ url(r'^admin/', include(admin.site.urls)),
+)
--- /dev/null
+from django.shortcuts import render
+#from django.contrib.sites import Site
+
+from django.conf import settings
+from quiz.models import Quiz
+
+
+def home(request):
+ quiz = Quiz.current()
+ return render(request, "home.html", locals())
--- /dev/null
+#!/bin/bash -
+#
+# File: git-archive-all.sh
+#
+# Description: A utility script that builds an archive file(s) of all
+# git repositories and submodules in the current path.
+# Useful for creating a single tarfile of a git super-
+# project that contains other submodules.
+#
+# Examples: Use git-archive-all.sh to create archive distributions
+# from git repositories. To use, simply do:
+#
+# cd $GIT_DIR; git-archive-all.sh
+#
+# where $GIT_DIR is the root of your git superproject.
+#
+# License: GPL3
+#
+###############################################################################
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+#
+###############################################################################
+
+# DEBUGGING
+set -e
+set -C # noclobber
+
+# TRAP SIGNALS
+trap 'cleanup' QUIT EXIT
+
+# For security reasons, explicitly set the internal field separator
+# to newline, space, tab
+OLD_IFS=$IFS
+IFS='
+ '
+
+function cleanup () {
+ rm -f $TMPFILE
+ rm -f $TOARCHIVE
+ IFS="$OLD_IFS"
+}
+
+function usage () {
+ echo "Usage is as follows:"
+ echo
+ echo "$PROGRAM <--version>"
+ echo " Prints the program version number on a line by itself and exits."
+ echo
+ echo "$PROGRAM <--usage|--help|-?>"
+ echo " Prints this usage output and exits."
+ echo
+ echo "$PROGRAM [--format <fmt>] [--prefix <path>] [--separate|-s] [output_file]"
+ echo " Creates an archive for the entire git superproject, and its submodules"
+ echo " using the passed parameters, described below."
+ echo
+ echo " If '--format' is specified, the archive is created with the named"
+ echo " git archiver backend. Obviously, this must be a backend that git archive"
+ echo " understands. The format defaults to 'tar' if not specified."
+ echo
+ echo " If '--prefix' is specified, the archive's superproject and all submodules"
+ echo " are created with the <path> prefix named. The default is to not use one."
+ echo
+ echo " If '--separate' or '-s' is specified, individual archives will be created"
+ echo " for each of the superproject itself and its submodules. The default is to"
+ echo " concatenate individual archives into one larger archive."
+ echo
+ echo " If 'output_file' is specified, the resulting archive is created as the"
+ echo " file named. This parameter is essentially a path that must be writeable."
+ echo " When combined with '--separate' ('-s') this path must refer to a directory."
+ echo " Without this parameter or when combined with '--separate' the resulting"
+ echo " archive(s) are named with a dot-separated path of the archived directory and"
+ echo " a file extension equal to their format (e.g., 'superdir.submodule1dir.tar')."
+}
+
+function version () {
+ echo "$PROGRAM version $VERSION"
+}
+
+# Internal variables and initializations.
+readonly PROGRAM=`basename "$0"`
+readonly VERSION=0.2
+
+OLD_PWD="`pwd`"
+TMPDIR=${TMPDIR:-/tmp}
+TMPFILE=`mktemp "$TMPDIR/$PROGRAM.XXXXXX"` # Create a place to store our work's progress
+TOARCHIVE=`mktemp "$TMPDIR/$PROGRAM.toarchive.XXXXXX"`
+OUT_FILE=$OLD_PWD # assume "this directory" without a name change by default
+SEPARATE=0
+
+FORMAT=tar
+PREFIX=
+TREEISH=HEAD
+
+# RETURN VALUES/EXIT STATUS CODES
+readonly E_BAD_OPTION=254
+readonly E_UNKNOWN=255
+
+# Process command-line arguments.
+while test $# -gt 0; do
+ case $1 in
+ --format )
+ shift
+ FORMAT="$1"
+ shift
+ ;;
+
+ --prefix )
+ shift
+ PREFIX="$1"
+ shift
+ ;;
+
+ --separate | -s )
+ shift
+ SEPARATE=1
+ ;;
+
+ --version )
+ version
+ exit
+ ;;
+
+ -? | --usage | --help )
+ usage
+ exit
+ ;;
+
+ -* )
+ echo "Unrecognized option: $1" >&2
+ usage
+ exit $E_BAD_OPTION
+ ;;
+
+ * )
+ break
+ ;;
+ esac
+done
+
+if [ ! -z "$1" ]; then
+ OUT_FILE="$1"
+ shift
+fi
+
+# Validate parameters; error early, error often.
+if [ $SEPARATE -eq 1 -a ! -d $OUT_FILE ]; then
+ echo "When creating multiple archives, your destination must be a directory."
+ echo "If it's not, you risk being surprised when your files are overwritten."
+ exit
+elif [ `git config -l | grep -q '^core\.bare=false'; echo $?` -ne 0 ]; then
+ echo "$PROGRAM must be run from a git working copy (i.e., not a bare repository)."
+ exit
+fi
+
+# Create the superproject's git archive
+git archive --format=$FORMAT --prefix="$PREFIX" $TREEISH > $TMPDIR/$(basename $(pwd)).$FORMAT
+echo $TMPDIR/$(basename $(pwd)).$FORMAT >| $TMPFILE # clobber on purpose
+superfile=`head -n 1 $TMPFILE`
+
+# find all '.git' dirs, these show us the remaining to-be-archived dirs
+find . -name '.git' -type d -print | sed -e 's/^\.\///' -e 's/\.git$//' | (grep -v '^$' || echo -n) >> $TOARCHIVE
+
+while read path; do
+ TREEISH=$(git submodule | grep "^ .*${path%/} " | cut -d ' ' -f 2) # git submodule does not list trailing slashes in $path
+ cd "$path"
+ git archive --format=$FORMAT --prefix="${PREFIX}$path" ${TREEISH:-HEAD} > "$TMPDIR"/"$(echo "$path" | sed -e 's/\//./g')"$FORMAT
+ if [ $FORMAT == 'zip' ]; then
+ # delete the empty directory entry; zipped submodules won't unzip if we don't do this
+ zip -d "$(tail -n 1 $TMPFILE)" "${PREFIX}${path%/}" >/dev/null # remove trailing '/'
+ fi
+ echo "$TMPDIR"/"$(echo "$path" | sed -e 's/\//./g')"$FORMAT >> $TMPFILE
+ cd "$OLD_PWD"
+done < $TOARCHIVE
+
+# Concatenate archives into a super-archive.
+if [ $SEPARATE -eq 0 ]; then
+ if [ $FORMAT == 'tar' ]; then
+ sed -e '1d' $TMPFILE | while read file; do
+ tar --concatenate -f "$superfile" "$file" && rm -f "$file"
+ done
+ elif [ $FORMAT == 'zip' ]; then
+ sed -e '1d' $TMPFILE | while read file; do
+ # zip incorrectly stores the full path, so cd and then grow
+ cd `dirname "$file"`
+ zip -g "$superfile" `basename "$file"` && rm -f "$file"
+ done
+ cd "$OLD_PWD"
+ fi
+
+ echo "$superfile" >| $TMPFILE # clobber on purpose
+fi
+
+while read file; do
+ mv "$file" "$OUT_FILE"
+done < $TMPFILE
--- /dev/null
+django-debug-toolbar
--- /dev/null
+# Django basics
+django>=1.3,<1.4
+South>=0.7