Initial import

This commit is contained in:
Guillaume Seguin 2012-06-27 23:28:35 +02:00
commit 8e1bf7b705
19 changed files with 970 additions and 0 deletions

3
.gitignore vendored Normal file
View file

@ -0,0 +1,3 @@
*.pyc
*.swp
*.swo

0
__init__.py Normal file
View file

7
apache/django.wsgi Executable file
View file

@ -0,0 +1,7 @@
import os, sys
sys.path.append (os.path.expanduser ('~gestion/www'))
os.environ['DJANGO_SETTINGS_MODULE'] = 'settings'
import django.core.handlers.wsgi
application = django.core.handlers.wsgi.WSGIHandler()

0
gestioncof/__init__.py Normal file
View file

65
gestioncof/admin.py Normal file
View file

@ -0,0 +1,65 @@
# coding: utf-8
from django.contrib import admin
from gestioncof.models import Survey, SurveyQuestion, SurveyQuestionAnswer
from gestioncof.models import Event, EventOption, EventOptionChoice
from django.core.urlresolvers import reverse
from django.utils.safestring import mark_safe
def add_link_field(target_model = '', field = '', link_text = unicode, desc_text = unicode):
def add_link(cls):
reverse_name = target_model or cls.model.__name__.lower()
def link(self, instance):
app_name = instance._meta.app_label
reverse_path = "admin:%s_%s_change" % (app_name, reverse_name)
link_obj = getattr(instance, field, None) or instance
if not link_obj.id:
return ""
url = reverse(reverse_path, args = (link_obj.id,))
return mark_safe("<a href='%s'>%s</a>" % (url, link_text(link_obj)))
link.allow_tags = True
link.short_description = desc_text(reverse_name + ' link')
cls.link = link
cls.readonly_fields = list(getattr(cls, 'readonly_fields', [])) + ['link']
return cls
return add_link
class SurveyQuestionAnswerInline(admin.TabularInline):
model = SurveyQuestionAnswer
@add_link_field(desc_text = lambda x: "Réponses", link_text = lambda x: "Éditer les réponses")
class SurveyQuestionInline(admin.TabularInline):
model = SurveyQuestion
class SurveyQuestionAdmin(admin.ModelAdmin):
inlines = [
SurveyQuestionAnswerInline,
]
class SurveyAdmin(admin.ModelAdmin):
inlines = [
SurveyQuestionInline,
]
@add_link_field()
class EventOptionChoiceInline(admin.StackedInline):
model = EventOptionChoice
@add_link_field()
class EventOptionInline(admin.StackedInline):
model = EventOption
class EventOptionAdmin(admin.ModelAdmin):
inlines = [
EventOptionChoiceInline,
]
class EventAdmin(admin.ModelAdmin):
inlines = [
EventOptionInline,
]
admin.site.register(Survey, SurveyAdmin)
admin.site.register(SurveyQuestion, SurveyQuestionAdmin)
admin.site.register(Event, EventAdmin)
admin.site.register(EventOption, EventOptionAdmin)

130
gestioncof/models.py Normal file
View file

@ -0,0 +1,130 @@
# coding: utf-8
from django.db import models
from django.contrib.auth.models import User
from django.utils.translation import ugettext_lazy as _
from django.db.models.signals import post_save
OCCUPATION_CHOICES = (
('exterieur', _(u"Extérieur")),
('1A', _(u"1A")),
('2A', _(u"2A")),
('3A', _(u"3A")),
('4A', _(u"4A")),
('archicube', _(u"Archicube")),
('doctorant', _(u"Doctorant")),
('CST', _(u"CST")),
)
TYPE_COTIZ_CHOICES = (
('etudiant', _(u"Étudiant")),
('normalien', _(u"Normalien")),
('exterieur', _(u"Extérieur")),
)
def choices_length (choices):
return reduce (lambda m, choice: max (m, len (choice[0])), choices, 0)
class CofProfile(models.Model):
user = models.OneToOneField(User)
login_clipper = models.CharField("Login clipper", max_length = 8)
is_cof = models.BooleanField("Membre du COF", default = False)
occupation = models.CharField (_(u"Occupation"),
default = "1A",
choices = OCCUPATION_CHOICES,
max_length = choices_length (OCCUPATION_CHOICES))
type_cotiz = models.CharField (_(u"Type de cotisation"),
default = "normalien",
choices = TYPE_COTIZ_CHOICES,
max_length = choices_length (TYPE_COTIZ_CHOICES))
mailing_cof = models.BooleanField("Recevoir les mails COF", default = True)
mailing_bda_revente = models.BooleanField("Recevoir les mails de revente de places BDA", default = True)
is_buro = models.BooleanField("Membre du Burô", default = False)
def create_user_profile(sender, instance, created, **kwargs):
if created:
CofProfile.objects.create(user = instance)
post_save.connect(create_user_profile, sender = User)
class Event(models.Model):
title = models.CharField("Titre", max_length = 200)
location = models.CharField("Lieu", max_length = 200)
start_date = models.DateField("Date de début", blank = True)
end_date = models.DateField("Date de fin", blank = True)
description = models.TextField("Description", blank = True)
registration_open = models.BooleanField("Inscriptions ouvertes", default = True)
class Meta:
verbose_name = "Événement"
def __unicode__(self):
return unicode(self.title)
class EventOption(models.Model):
event = models.ForeignKey(Event)
name = models.CharField("Option", max_length = 200)
class Meta:
verbose_name = "Option"
def __unicode__(self):
return unicode(self.name)
class EventOptionChoice(models.Model):
event_option = models.ForeignKey(EventOption)
value = models.CharField("Valeur", max_length = 200)
class Meta:
verbose_name = "Choix"
def __unicode__(self):
return unicode(self.value)
class EventRegistration(models.Model):
user = models.ForeignKey(User)
event = models.ForeignKey(Event)
options = models.ManyToManyField(EventOptionChoice)
paid = models.BooleanField("A payé", default = False)
class Meta:
verbose_name = "Inscription"
class Survey(models.Model):
title = models.CharField("Titre", max_length = 200)
details = models.TextField("Détails", blank = True)
survey_open = models.BooleanField("Sondage ouvert", default = True)
class Meta:
verbose_name = "Sondage"
def __unicode__(self):
return unicode(self.title)
class SurveyQuestion(models.Model):
survey = models.ForeignKey(Survey, related_name = "questions")
question = models.CharField("Question", max_length = 200)
multi_answers = models.BooleanField("Choix multiples", default = False)
class Meta:
verbose_name = "Question"
def __unicode__(self):
return unicode(self.question)
class SurveyQuestionAnswer(models.Model):
survey_question = models.ForeignKey(SurveyQuestion, related_name = "answers")
answer = models.CharField("Réponse", max_length = 200)
class Meta:
verbose_name = "Réponse"
def __unicode__(self):
return unicode(self.answer)
class SurveyAnswer(models.Model):
user = models.ForeignKey(User)
survey = models.ForeignKey(Survey)
answers = models.ManyToManyField(SurveyQuestionAnswer)
class Meta:
verbose_name = "Réponses"

24
gestioncof/shared.py Normal file
View file

@ -0,0 +1,24 @@
from django.contrib.sites.models import Site
from django.conf import settings
from django_cas.backends import CASBackend
class COFCASBackend(CASBackend):
def authenticate(self, ticket, service):
"""Authenticates CAS ticket and retrieves user data"""
user = super(COFCASBackend, self).authenticate(ticket, service)
profile = user.get_profile()
if not profile.login_clipper:
profile.login_clipper = user.username
profile.save()
if not user.email:
user.email = settings.CAS_EMAIL_FORMAT % profile.login_clipper
user.save()
return user
def context_processor (request):
'''Append extra data to the context of the given request'''
data = {
"user": request.user,
"site": Site.objects.get_current(),
}
return data

16
gestioncof/tests.py Normal file
View file

@ -0,0 +1,16 @@
"""
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.
"""
from django.test import TestCase
class SimpleTest(TestCase):
def test_basic_addition(self):
"""
Tests that 1 + 1 always equals 2.
"""
self.assertEqual(1 + 1, 2)

108
gestioncof/views.py Normal file
View file

@ -0,0 +1,108 @@
from django.shortcuts import redirect, get_object_or_404
from django.template import RequestContext, loader
from django.http import HttpResponse, HttpResponseRedirect, Http404
from django.core.urlresolvers import reverse
from django.contrib.auth.models import User
from django.contrib.auth.decorators import login_required
from django import forms
from django.forms.widgets import RadioSelect, CheckboxSelectMultiple
from gestioncof.models import Survey, SurveyQuestion, SurveyQuestionAnswer, SurveyAnswer
from gestioncof.models import Event, EventOption, EventOptionChoice, EventRegistration
def render_page (request, data, template):
template = loader.get_template (template)
context = RequestContext (request, data)
return HttpResponse (template.render (context))
@login_required
def home(request):
data = {"surveys": Survey.objects.filter(survey_open = True).all(),
"events": Event.objects.filter(registration_open = True).all()}
return render_page(request, data, "home.html")
def login(request):
if request.user.is_authenticated():
return redirect("gestioncof.views.home")
return render_page(request, {}, "login_switch.html")
@login_required
def logout(request):
if request.user.get_profile().login_clipper:
return redirect("django_cas.views.logout")
else:
return redirect("django.contrib.auth.views.logout")
class SurveyForm(forms.Form):
def __init__(self, *args, **kwargs):
survey = kwargs.pop("survey")
current_answers = kwargs.pop("current_answers", None)
super(SurveyForm, self).__init__(*args, **kwargs)
answers = {}
if current_answers:
for answer in current_answers.all():
if answer.survey_question.id not in answers:
answers[answer.survey_question.id] = [answer.id]
else:
answers[answer.survey_question.id].append(answer.id)
for question in survey.questions.all():
choices = [(answer.id, answer.answer) for answer in question.answers.all()]
if question.multi_answers:
initial = [] if question.id not in answers else answers[question.id]
field = forms.MultipleChoiceField(label = question.question,
choices = choices,
widget = CheckboxSelectMultiple,
required = False,
initial = initial)
else:
initial = None if question.id not in answers else answers[question.id][0]
field = forms.ChoiceField(label = question.question,
choices = choices,
widget = RadioSelect,
required = False,
initial = initial)
field.question_id = question.id
self.fields["question_%d" % question.id] = field
def answers(self):
for name, value in self.cleaned_data.items():
if name.startswith('question_'):
yield (self.fields[name].question_id, value)
@login_required
def survey(request, survey_id):
survey = get_object_or_404(Survey, id = survey_id)
if not survey.survey_open:
raise Http404
success = False
if request.method == "POST":
form = SurveyForm(request.POST, survey = survey)
if form.is_valid():
all_answers = []
for question_id, answers_ids in form.answers():
question = get_object_or_404(SurveyQuestion, id = question_id,
survey = survey)
if type(answers_ids) != list:
answers_ids = [answers_ids]
if not question.multi_answers and len(answers_ids) > 1:
raise Http404
for answer_id in answers_ids:
answer_id = int(answer_id)
answer = SurveyQuestionAnswer.objects.get(
id = answer_id,
survey_question = question)
all_answers.append(answer)
try:
current_answer = SurveyAnswer.objects.get(user = request.user, survey = survey)
except SurveyAnswer.DoesNotExist:
current_answer = SurveyAnswer(user = request.user, survey = survey)
current_answer.save()
current_answer.answers = all_answers
current_answer.save()
success = True
else:
try:
current_answer = SurveyAnswer.objects.get(user = request.user, survey = survey)
form = SurveyForm(survey = survey, current_answers = current_answer.answers)
except SurveyAnswer.DoesNotExist:
form = SurveyForm(survey = survey)
return render_page(request, {"survey": survey, "form": form, "success": success}, "survey.html")

14
manage.py Normal file
View file

@ -0,0 +1,14 @@
#!/usr/bin/env python
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)

298
media/cof.css Normal file
View file

@ -0,0 +1,298 @@
html,body {
}
@font-face {
font-family: 'Droid Serif';
font-style: normal;
font-weight: bold;
src: local('Droid Serif Bold'), local('DroidSerif-Bold'), url('droidserif.woff') format('woff');
}
.spacer {
clear: both;
}
#cof a:link, #cof a:active, #cof a:visited {
color: #111;
background: transparent;
}
#cof a:hover {
color: #444;
background: transparent;
}
#cof form {
display: block;
padding: 0;
width: 100%;
}
#cof fieldset {
border: 0;
margin: 0;
padding: 0;
float: left;
clear: none;
width: auto;
}
#cof fieldset legend {
display: none;
}
#cof #main-login-container {
width: 500px;
margin: 7em auto;
}
#cof #main-login {
width: 500px;
border: 15px solid #333;
-webkit-border-radius: 20px;
-moz-border-radius: 20px;
border-radius: 20px;
}
#cof #main-container {
width: 800px;
margin: 7em auto;
}
#cof #main {
width: 800px;
border: 15px solid #333;
-webkit-border-radius: 20px;
-moz-border-radius: 20px;
border-radius: 20px;
padding: 2em;
box-shadow: 0 0 100px #AAA inset;
}
#cof #main #main-content {
font-size: 1.25em;
margin-top: 10px;
}
#cof #main #main-content ul {
line-height: 1.3em;
}
#cof #main h1 {
font-size: 3em;
}
#cof #main h1 a {
color: #333;
text-decoration: none;
}
#cof #main h2 {
font-size: 1.5em;
margin-bottom: 10px;
}
#cof #main h3 {
font-size: 1.3em;
}
#cof #main p {
margin-top: 8px;
margin-bottom: 8px;
}
#cof #main form li {
list-style: none;
}
#cof .success {
font-weight: bold;
color: #00B000;
background-color: transparent;
}
#cof #main form ul.errorlist li {
font-weight: bold;
color: #B00000;
background-color: transparent;
list-style: disc;
}
#cof #main-login.login_block {
padding: 2em;
box-shadow: 0 0 100px #AAA inset;
}
#cof a#login_clipper, #cof a#login_outsider {
float: left;
display: block;
width: 250px;
height: 200px;
text-align: center;
font-family: 'Droid Serif', serif;
font-size: 2em;
font-weight: bold;
line-height: 190px;
text-decoration: none;
color: #FFF;
}
#cof a#login_clipper {
background-color: #123E96;
box-shadow: 0 0 100px #040C78 inset;
}
#cof a#login_clipper:hover {
background-color: #164BB6;
}
#cof a#login_outsider {
background-color: #961221;
box-shadow: 0 0 100px #780411 inset;
}
#cof a#login_outsider:hover {
background-color: #B31729;
}
#cof #main-login label {
font-size: 11px;
}
#cof #main-login label span.accesskey {
text-decoration: underline;
}
#cof #main-login input {
letter-spacing: 1px;
}
#cof #main-login .btn-row {
float: right;
}
#cof .btn-submit {
float: none;
clear: none;
display: inline;
letter-spacing: 0;
color: #333;
padding: 5px;
text-transform: uppercofe;
font-variant: small-caps;
border: 1px solid #ccc;
background: -webkit-gradient(linear, 0% 0%, 0% 100%, from(#EEE), to(#CCC));
background: -moz-linear-gradient(19% 75% 90deg,#EEE, #CCC);
background: linear-gradient(center top, #EEE, #CCC);
}
#cof #main-login .btn-reset {
float: none;
clear: none;
margin-left: 5px;
border: 0;
border-left: 1px solid #ddd;
background: transparent;
color: #777;
text-transform: lowercase;
letter-spacing: 0;
}
/* RESET --------------------------------- */
/* reset some properties for elements since defaults are not crossbrowser - http: //meyerweb.com/eric/thoughts/2007/05/01/reset-reloaded/ */
html,body,div,span,h1,h2,h3,p,a,img,ul,li,fieldset,form,label,legend {
margin: 0;
padding: 0;
border: 0;
outline: 0;
font-weight: inherit;
font-style: inherit;
font-size: 100%;
font-family: inherit;
vertical-align: baseline;
}
:focus {
outline: 0;
}
ul {
font-size: 1.1em;
padding: 6px 0 6px 12px;
}
body {
font: normal 400 62.5%/1.0 Verdana, sans-serif;
background-color: #eee;
color: #333;
}
/* HEADER --------------------------------- */
#header h1 {
font-family: 'Droid Serif', serif;
font-weight: bold;
font-size: 18px;
margin-bottom: 5px;
}
tt {
font-weight: bold;
}
.error {
color: #BB0000;
background-color: transparent;
}
/* FORMS --------------------------------- */
input {
border-width: 1px;
font-family: Verdana,sans-serif;
font-size: 1.1em;
color: #000;
padding: 3px;
min-height: 1.5em;
}
input[type="text"], input[type=password] {
border: 2px solid #888;
-webkit-border-radius: 8px;
-moz-border-radius: 8px;
border-radius: 8px;
box-shadow: 0 0 12px #AAA inset;
min-height: 2em;
}
hr {
border: 0;
height: 1px;
background: #333;
background: -webkit-gradient(linear, left top, right top, color-stop(0%,hsla(0,0%,70%,0)), color-stop(50%,hsla(0,0%,70%,.75)), color-stop(100%,hsla(0,0%,70%,0)));
background: -webkit-linear-gradient(left, hsla(0,0%,70%,0) 0%, hsla(0,0%,70%,.75) 50%, hsla(0,0%,70%,0) 100%);
background: -moz-linear-gradient(left, hsla(0,0%,70%,0) 0%, hsla(0,0%,70%,.75) 50%, hsla(0,0%,70%,0) 100%);
background: -ms-linear-gradient(left, hsla(0,0%,70%,0) 0%, hsla(0,0%,70%,.75) 50%, hsla(0,0%,70%,0) 100%);
background: -o-linear-gradient(left, hsla(0,0%,70%,0) 0%, hsla(0,0%,70%,.75) 50%, hsla(0,0%,70%,0) 100%);
background: linear-gradient(left, hsla(0,0%,70%,0) 0%, hsla(0,0%,70%,.75) 50%, hsla(0,0%,70%,0) 100%);
}
.fm-v div.row {
margin: 0;
padding: .5em 0;
width: 100%;
}
.fm-v div.row label {
float: left;
width: 100%;
line-height: 1.5;
}
.fm-v div.row input.btn-submit {
display: block;
margin: 0;
}
.fm-v div.row.fl-controls-left {
width: 50%;
float: left;
}

168
settings.py Normal file
View file

@ -0,0 +1,168 @@
# Django settings for cof project.
DEBUG = True
TEMPLATE_DEBUG = DEBUG
ADMINS = (
('Guillaume Seguin', 'guillaume@segu.in'),
)
MANAGERS = ADMINS
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql', # Add 'postgresql_psycopg2', 'postgresql', 'mysql', 'sqlite3' or 'oracle'.
'NAME': 'cof_gestion', # Or path to database file if using sqlite3.
'USER': 'cof_gestion', # Not used with sqlite3.
'PASSWORD': '1OjKotIbmyro', # 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 = 'Europe/Paris'
# Language code for this installation. All choices can be found here:
# http://www.i18nguy.com/unicode/language-identifiers.html
LANGUAGE_CODE = 'fr-fr'
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 = ''
# 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 = '/gestion/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 = '/home/gestion/www/static'
# URL prefix for static files.
# Example: "http://media.lawrence.com/static/"
STATIC_URL = '/gestion/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 = '/gestion/static/grappelli/'
GRAPPELLI_ADMIN_HEADLINE = "GestioCOF"
GRAPPELLI_ADMIN_TITLE = "GestioCOF"
# 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',
)
# Make this unique, and don't share it with anybody.
SECRET_KEY = '1d%3zqeyj8dk^@afz9=q12gs&&5k@4qx)5%uc_(&%01)d&74af'
# 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',
)
TEMPLATE_CONTEXT_PROCESSORS = (
"django.core.context_processors.auth",
"django.core.context_processors.debug",
"django.core.context_processors.i18n",
"django.core.context_processors.media",
"django.core.context_processors.static",
"gestioncof.shared.context_processor",
)
MIDDLEWARE_CLASSES = (
'django.middleware.common.CommonMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
# 'django_cas.middleware.CASMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
)
ROOT_URLCONF = 'urls'
TEMPLATE_DIRS = (
"/home/gestion/www/templates/gestioncof",
)
LOGIN_URL = "/gestion/login"
LOGIN_REDIRECT_URL = "/gestion/"
CAS_SERVER_URL = 'https://cas.eleves.ens.fr/'
CAS_IGNORE_REFERER = True
CAS_REDIRECT_URL = '/gestion/'
CAS_EMAIL_FORMAT = "%s@clipper.ens.fr"
AUTH_PROFILE_MODULE = 'gestioncof.CofProfile'
AUTHENTICATION_BACKENDS = (
'django.contrib.auth.backends.ModelBackend',
'gestioncof.shared.COFCASBackend',
)
INSTALLED_APPS = (
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.sites',
'django.contrib.messages',
'django.contrib.staticfiles',
'grappelli',
'django.contrib.admin',
'django.contrib.admindocs',
'gestioncof',
)
# 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,
},
}
}

View file

@ -0,0 +1,11 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" lang="fr">
<head>
<title>{{ site.name }}</title>
<link type="text/css" rel="stylesheet" href="{{ MEDIA_URL }}/cof.css" />
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
</head>
<body id="cof">
{% block content %}{% endblock %}
</body>
</html>

View file

@ -0,0 +1,16 @@
{% extends "base.html" %}
{% block content %}
<div id="main-container">
<div id="main">
<div id="header">
<h1>{% block title %}<a href="{% url gestioncof.views.home %}">{{ site.name }}</a>{% endblock %}</h1>
<hr />
<div id="main-content">
{% block realcontent %}{% endblock %}
</div>
</div>
</div>
</div>
{% endblock %}

View file

@ -0,0 +1,28 @@
{% extends "base_title.html" %}
{% block realcontent %}
<h2>Bienvenue, {% if user.first_name %}{{ user.first_name }}{% else %}<tt>{{ user.username }}</tt>{% endif %}</h2>
{% if events %}
<h3>Événements</h3>
<ul>
{% for event in events %}
<li><a href="{% url gestioncof.views.event event.id %}">{{ event.title }}</a></li>
{% endfor %}
</ul>
{% endif %}
{% if surveys %}
<h3>Sondages</h3>
<ul>
{% for survey in surveys %}
<li><a href="{% url gestioncof.views.survey survey.id %}">{{ survey.title }}</a></li>
{% endfor %}
</ul>
{% endif %}
<h3>Divers</h3>
<ul>
{% if user.is_buro or user.is_staff %}
<li><a href="{% url admin:index %}">Administration</a></li>
{% endif %}
<li><a href="{% url gestioncof.views.logout %}">Se déconnecter</a></li>
</ul>
{% endblock %}

View file

@ -0,0 +1,32 @@
{% extends "base.html" %}
{% block content %}
<div id="main-login-container">
<div id="main-login" class="login_block">
<div id="header">
<h1>{{ site.name }} &ndash; Connexion</h1>
</div>
{% if form.errors %}
<p class="error">Identifiants incorrects.</p>
{% endif %}
<form method="post" action="{% url django.contrib.auth.views.login %}">
{% csrf_token %}
<table>
<tr>
<td>{{ form.username.label_tag }}</td>
<td>{{ form.username }}</td>
</tr>
<tr>
<td>{{ form.password.label_tag }}</td>
<td>{{ form.password }}</td>
</tr>
</table>
<input type="submit" name="submit" class="btn-submit" value="SE CONNECTER" />
<input type="hidden" name="next" value="{{ next }}" />
</form>
</div>
</div>
{% endblock %}

View file

@ -0,0 +1,16 @@
{% extends "base.html" %}
{% block content %}
<div id="main-login-container">
<div id="main-login">
<a id="login_clipper" href="{% url django_cas.views.login %}">
Compte clipper
</a>
<a id="login_outsider" href="{% url django.contrib.auth.views.login %}">
Extérieur
</a>
<div class="spacer"></div>
</div>
</div>
{% endblock %}

View file

@ -0,0 +1,16 @@
{% extends "base_title.html" %}
{% block realcontent %}
<h2>Sondage: {{ survey.title }}</h2>
{% if success %}
<p class="success">Votre réponse a bien été enregistrée ! Vous pouvez cependant la modifier jusqu'à la fin du sondage.</p>
{% endif %}
{% if survey.details %}
<p>{{ survey.details }}</p>
{% endif %}
<form method="post" action="{% url gestioncof.views.survey survey.id %}">
{% csrf_token %}
{{ form.as_p }}
<input type="submit" class="btn-submit" value="Enregistrer" />
</form>
{% endblock %}

18
urls.py Normal file
View file

@ -0,0 +1,18 @@
from django.conf.urls.defaults import patterns, include, url
from django.contrib import admin
admin.autodiscover()
urlpatterns = patterns('',
url(r'^$', 'gestioncof.views.home', name='home'),
url(r'^cas/login$', 'django_cas.views.login'),
url(r'^cas/logout$', 'django_cas.views.logout'),
url(r'^outsider/login$', 'django.contrib.auth.views.login', {'template_name': 'login.html'}),
url(r'^outsider/logout$', 'django.contrib.auth.views.logout', {'next_page': '/gestion/'}),
url(r'^login$', 'gestioncof.views.login'),
url(r'^logout$', 'gestioncof.views.logout'),
url(r'^survey/(?P<survey_id>\d+)$', 'gestioncof.views.survey'),
url(r'^admin/doc/', include('django.contrib.admindocs.urls')),
url(r'^admin/', include(admin.site.urls)),
url(r'^grappelli/', include('grappelli.urls')),
)