diff --git a/apache/wsgi.py b/apache/wsgi.py index b7a1eb92..177542a8 100644 --- a/apache/wsgi.py +++ b/apache/wsgi.py @@ -1,3 +1,5 @@ +# -*- coding: utf-8 -*- + """ WSGI config for myproject project. It exposes the WSGI callable as a module-level variable named ``application``. @@ -5,6 +7,10 @@ For more information on this file, see https://docs.djangoproject.com/en/1.7/howto/deployment/wsgi/ """ +from __future__ import division +from __future__ import print_function +from __future__ import unicode_literals + import os from django.core.wsgi import get_wsgi_application diff --git a/bda/admin.py b/bda/admin.py index 35f79b8c..eb8d3106 100644 --- a/bda/admin.py +++ b/bda/admin.py @@ -1,4 +1,8 @@ -# coding: utf-8 +# -*- coding: utf-8 -*- + +from __future__ import division +from __future__ import print_function +from __future__ import unicode_literals from django.core.mail import send_mail @@ -52,9 +56,9 @@ class ParticipantAdmin(admin.ModelAdmin): def total(self, obj): tot = obj.total if tot: - return u"%.02f €" % tot + return "%.02f €" % tot else: - return u"0 €" + return "0 €" total.admin_order_field = "total" total.short_description = "Total à payer" list_display = ("user", "nb_places", "total", "paid", "paymenttype", @@ -70,7 +74,7 @@ class ParticipantAdmin(admin.ModelAdmin): for member in queryset.all(): attribs = member.attributions.all() if len(attribs) == 0: - mail = u"""Cher-e %s, + mail = """Cher-e %s, Tu t'es inscrit-e pour le tirage au sort du BdA. Malheureusement, tu n'as obtenu aucune place. @@ -85,7 +89,7 @@ Le Bureau des Arts name = member.user.get_full_name() mail = mail % name else: - mail = u"""Cher-e %s, + mail = """Cher-e %s, Tu t'es inscrit-e pour le tirage au sort du BdA. Tu as été sélectionné-e pour les spectacles suivants : @@ -120,7 +124,7 @@ Le Bureau des Arts attribs_text = "" name = member.user.get_full_name() for attrib in attribs: - attribs_text += u"- 1 place pour %s\n" % attrib + attribs_text += "- 1 place pour %s\n" % attrib deadline = member.tirage.fermeture + timedelta(days=7) mail = mail % (name, attribs_text, deadline.strftime('%d %b %Y')) @@ -129,14 +133,14 @@ Le Bureau des Arts fail_silently=True) count = len(queryset.all()) if count == 1: - message_bit = u"1 membre a" + message_bit = "1 membre a" plural = "" else: - message_bit = u"%d membres ont" % count + message_bit = "%d membres ont" % count plural = "s" - self.message_user(request, u"%s été informé%s avec succès." + self.message_user(request, "%s été informé%s avec succès." % (message_bit, plural)) - send_attribs.short_description = u"Envoyer les résultats par mail" + send_attribs.short_description = "Envoyer les résultats par mail" class AttributionAdminForm(forms.ModelForm): @@ -147,8 +151,8 @@ class AttributionAdminForm(forms.ModelForm): if participant and spectacle: if participant.tirage != spectacle.tirage: raise forms.ValidationError( - u"Erreur : le participant et le spectacle n'appartiennent" - u"pas au même tirage") + "Erreur : le participant et le spectacle n'appartiennent" + "pas au même tirage") return cleaned_data diff --git a/bda/algorithm.py b/bda/algorithm.py index 005e714f..bf9b690f 100644 --- a/bda/algorithm.py +++ b/bda/algorithm.py @@ -1,6 +1,8 @@ -# coding: utf-8 +# -*- coding: utf-8 -*- from __future__ import division +from __future__ import print_function +from __future__ import unicode_literals from django.db.models import Max diff --git a/bda/autocomplete_light_registry.py b/bda/autocomplete_light_registry.py index 7aa43b07..6c2f3ea6 100644 --- a/bda/autocomplete_light_registry.py +++ b/bda/autocomplete_light_registry.py @@ -1,3 +1,9 @@ +# -*- coding: utf-8 -*- + +from __future__ import division +from __future__ import print_function +from __future__ import unicode_literals + import autocomplete_light from bda.models import Participant, Spectacle diff --git a/bda/forms.py b/bda/forms.py index 213ec17b..9f5e3890 100644 --- a/bda/forms.py +++ b/bda/forms.py @@ -1,4 +1,8 @@ -# coding: utf-8 +# -*- coding: utf-8 -*- + +from __future__ import division +from __future__ import print_function +from __future__ import unicode_literals from django import forms from django.forms.models import BaseInlineFormSet @@ -33,8 +37,8 @@ class TokenForm(forms.Form): class SpectacleModelChoiceField(forms.ModelChoiceField): def label_from_instance(self, obj): - return u"%s le %s (%s) à %.02f€" % (obj.title, obj.date_no_seconds(), - obj.location, obj.price) + return "%s le %s (%s) à %.02f€" % (obj.title, obj.date_no_seconds(), + obj.location, obj.price) class ResellForm(forms.Form): diff --git a/bda/management/__init__.py b/bda/management/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/bda/management/commands/__init__.py b/bda/management/commands/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/bda/management/commands/sendrappels.py b/bda/management/commands/sendrappels.py new file mode 100644 index 00000000..1e8da240 --- /dev/null +++ b/bda/management/commands/sendrappels.py @@ -0,0 +1,28 @@ +# -*- coding: utf-8 -*- + +from __future__ import unicode_literals + +from django.core.management.base import BaseCommand +from django.utils import timezone +from datetime import timedelta +from bda.models import Spectacle + + +class Command(BaseCommand): + help = 'Envoie les mails de rappel des spectacles dont la date ' \ + 'approche.\nNe renvoie pas les mails déjà envoyés.' + + def handle(self, *args, **options): + now = timezone.now() + delay = timedelta(days=4) + shows = Spectacle.objects \ + .filter(date__range=(now, now+delay)) \ + .filter(tirage__active=True) \ + .filter(rappel_sent__isnull=True) \ + .all() + for show in shows: + show.send_rappel() + self.stdout.write( + 'Mails de rappels pour %s envoyés avec succès.' % show) + if not shows: + self.stdout.write('Aucun mail à envoyer.') diff --git a/bda/models.py b/bda/models.py index 37c43479..ba72416a 100644 --- a/bda/models.py +++ b/bda/models.py @@ -1,4 +1,8 @@ -# coding: utf-8 +# -*- coding: utf-8 -*- + +from __future__ import division +from __future__ import print_function +from __future__ import unicode_literals import calendar @@ -8,6 +12,7 @@ from django.template import loader, Context from django.core import mail from django.conf import settings from django.utils import timezone +from django.utils.encoding import python_2_unicode_compatible def render_template(template_name, data): @@ -16,6 +21,7 @@ def render_template(template_name, data): return tmpl.render(ctxt) +@python_2_unicode_compatible class Tirage(models.Model): title = models.CharField("Titre", max_length=300) ouverture = models.DateTimeField("Date et heure d'ouverture du tirage") @@ -28,18 +34,20 @@ class Tirage(models.Model): def date_no_seconds(self): return self.fermeture.strftime('%d %b %Y %H:%M') - def __unicode__(self): - return u"%s - %s" % (self.title, self.date_no_seconds()) + def __str__(self): + return "%s - %s" % (self.title, self.date_no_seconds()) +@python_2_unicode_compatible class Salle(models.Model): name = models.CharField("Nom", max_length=300) address = models.TextField("Adresse") - def __unicode__(self): + def __str__(self): return self.name +@python_2_unicode_compatible class Spectacle(models.Model): title = models.CharField("Titre", max_length=300) date = models.DateTimeField("Date & heure") @@ -59,7 +67,7 @@ class Spectacle(models.Model): ordering = ("priority", "date", "title",) def __repr__(self): - return u"[%s]" % self.__unicode__() + return "[%s]" % self def timestamp(self): return "%d" % calendar.timegm(self.date.utctimetuple()) @@ -67,9 +75,9 @@ class Spectacle(models.Model): def date_no_seconds(self): return self.date.strftime('%d %b %Y %H:%M') - def __unicode__(self): - return u"%s - %s, %s, %.02f€" % (self.title, self.date_no_seconds(), - self.location, self.price) + def __str__(self): + return "%s - %s, %s, %.02f€" % (self.title, self.date_no_seconds(), + self.location, self.price) def send_rappel(self): # On récupère la liste des participants @@ -104,13 +112,14 @@ class Spectacle(models.Model): return members.values() PAYMENT_TYPES = ( - ("cash", u"Cash"), + ("cash", "Cash"), ("cb", "CB"), - ("cheque", u"Chèque"), - ("autre", u"Autre"), + ("cheque", "Chèque"), + ("autre", "Autre"), ) +@python_2_unicode_compatible class Participant(models.Model): user = models.ForeignKey(User) choices = models.ManyToManyField(Spectacle, @@ -119,14 +128,14 @@ class Participant(models.Model): attributions = models.ManyToManyField(Spectacle, through="Attribution", related_name="attributed_to") - paid = models.BooleanField(u"A payé", default=False) - paymenttype = models.CharField(u"Moyen de paiement", + paid = models.BooleanField("A payé", default=False) + paymenttype = models.CharField("Moyen de paiement", max_length=6, choices=PAYMENT_TYPES, blank=True) tirage = models.ForeignKey(Tirage) - def __unicode__(self): - return u"%s" % (self.user) + def __str__(self): + return "%s - %s" % (self.user, self.tirage.title) DOUBLE_CHOICES = ( ("1", "1 place"), @@ -135,6 +144,7 @@ DOUBLE_CHOICES = ( ) +@python_2_unicode_compatible class ChoixSpectacle(models.Model): participant = models.ForeignKey(Participant) spectacle = models.ForeignKey(Spectacle, related_name="participants") @@ -151,6 +161,11 @@ class ChoixSpectacle(models.Model): return self.double_choice == "autoquit" autoquit = property(get_autoquit) + def __str__(self): + return "Vœux de %s pour %s" % ( + self.participant.user.get_full_name, + self.spectacle.title) + class Meta: ordering = ("priority",) unique_together = (("participant", "spectacle",),) @@ -158,10 +173,11 @@ class ChoixSpectacle(models.Model): verbose_name_plural = "voeux" +@python_2_unicode_compatible class Attribution(models.Model): participant = models.ForeignKey(Participant) spectacle = models.ForeignKey(Spectacle, related_name="attribues") - given = models.BooleanField(u"Donnée", default=False) + given = models.BooleanField("Donnée", default=False) - def __unicode__(self): - return u"%s -- %s" % (self.participant, self.spectacle) + def __str__(self): + return "%s -- %s" % (self.participant, self.spectacle) diff --git a/bda/tests.py b/bda/tests.py index 501deb77..22efc5a2 100644 --- a/bda/tests.py +++ b/bda/tests.py @@ -1,3 +1,4 @@ +# -*- coding: utf-8 -*- """ This file demonstrates writing tests using the unittest module. These will pass when you run "manage.py test". @@ -5,6 +6,11 @@ when you run "manage.py test". Replace this with more appropriate tests for your application. """ +from __future__ import division +from __future__ import print_function +from __future__ import unicode_literals + + from django.test import TestCase diff --git a/bda/urls.py b/bda/urls.py index 268bb352..4e5811a1 100644 --- a/bda/urls.py +++ b/bda/urls.py @@ -1,5 +1,9 @@ # -*- coding: utf-8 -*- +from __future__ import division +from __future__ import print_function +from __future__ import unicode_literals + from django.conf.urls import url, patterns from bda.views import SpectacleListView diff --git a/bda/views.py b/bda/views.py index df8274c4..bf666f08 100644 --- a/bda/views.py +++ b/bda/views.py @@ -1,6 +1,8 @@ -# coding: utf-8 +# -*- coding: utf-8 -*- from __future__ import division +from __future__ import print_function +from __future__ import unicode_literals from django.shortcuts import render, get_object_or_404 from django.contrib.auth.decorators import login_required @@ -64,7 +66,7 @@ def etat_places(request, tirage_id): def _hash_queryset(queryset): - data = serializers.serialize("json", queryset) + data = serializers.serialize("json", queryset).encode() hasher = hashlib.sha256() hasher.update(data) return hasher.hexdigest() @@ -145,7 +147,7 @@ def inscription(request, tirage_id): return render(request, "resume_inscription.html", {"error_title": "C'est fini !", "error_description": - u"Tirage au sort dans la journée !", + "Tirage au sort dans la journée !", "choices": choices}) def formfield_callback(f, **kwargs): @@ -194,7 +196,7 @@ def do_tirage(request, tirage_id): tirage_elt = get_object_or_404(Tirage, id=tirage_id) form = TokenForm(request.POST) if not form.is_valid(): - return tirage(request) + return tirage(request, tirage_id) start = time.time() data = {} shows = tirage_elt.spectacle_set.select_related().all() @@ -221,7 +223,7 @@ def do_tirage(request, tirage_id): deficit = (show.slots - len(members)) * show.price total_sold += show.slots * show.price if deficit >= 0: - if u"Opéra" in show.location.name: + if "Opéra" in show.location.name: opera_deficit += deficit total_deficit += deficit data["total_sold"] = total_sold - total_deficit @@ -279,7 +281,7 @@ def do_resell(request, form): spectacle = form.cleaned_data["spectacle"] count = form.cleaned_data["count"] places = "2 places" if count == "2" else "une place" - mail = u"""Bonjour, + mail = """Bonjour, Je souhaite revendre %s pour %s le %s (%s) à %.02f€. Contactez moi par email si vous êtes intéressé·e·s ! diff --git a/cof/settings_dev.py b/cof/settings_dev.py index 1ef05f8c..502cb0ee 100644 --- a/cof/settings_dev.py +++ b/cof/settings_dev.py @@ -1,5 +1,4 @@ -# -*-coding:utf-8 -* - +# -*- coding: utf-8 -*- """ Django settings for cof project. @@ -10,6 +9,10 @@ For the full list of settings and their values, see https://docs.djangoproject.com/en/1.8/ref/settings/ """ +from __future__ import division +from __future__ import print_function +from __future__ import unicode_literals + # Build paths inside the project like this: os.path.join(BASE_DIR, ...) import os diff --git a/cof/urls.py b/cof/urls.py index b5d2b65a..ee9d8457 100644 --- a/cof/urls.py +++ b/cof/urls.py @@ -1,15 +1,17 @@ -# -*-coding:utf-8 -* +# -*- coding: utf-8 -*- + +from __future__ import division +from __future__ import print_function +from __future__ import unicode_literals from django.conf import settings from django.conf.urls import patterns, include, url from django.conf.urls.static import static +from django.contrib import admin +from django.views.generic.base import TemplateView import autocomplete_light -from django.contrib import admin - -from django.views.generic.base import TemplateView - from gestioncof.urls import export_patterns, petitcours_patterns, \ surveys_patterns, events_patterns @@ -75,7 +77,7 @@ urlpatterns = patterns( url(r'^utile_bda/bda_revente$', 'gestioncof.views.liste_bdarevente'), ) + \ (static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT) - if settings.DEBUG - else []) + if settings.DEBUG + else []) # Si on est en production, MEDIA_ROOT est servi par Apache. # Il faut dire à Django de servir MEDIA_ROOT lui-même en développement. diff --git a/gestioncof/admin.py b/gestioncof/admin.py index 8a1fb431..86935f64 100644 --- a/gestioncof/admin.py +++ b/gestioncof/admin.py @@ -1,4 +1,8 @@ -# coding: utf-8 +# -*- coding: utf-8 -*- + +from __future__ import division +from __future__ import print_function +from __future__ import unicode_literals from django.contrib import admin from gestioncof.models import * @@ -8,12 +12,13 @@ from django.contrib.auth.admin import UserAdmin from django.core.urlresolvers import reverse from django.utils.safestring import mark_safe from django.utils.translation import ugettext_lazy as _ +import django.utils.six as six import autocomplete_light -def add_link_field(target_model='', field='', link_text=unicode, - desc_text=unicode): +def add_link_field(target_model='', field='', link_text=six.text_type, + desc_text=six.text_type): def add_link(cls): reverse_name = target_model or cls.model.__name__.lower() @@ -168,17 +173,21 @@ class UserProfileAdmin(UserAdmin): ] +# FIXME: This is absolutely horrible. def user_unicode(self): if self.first_name and self.last_name: - return u"%s %s (%s)" % (self.first_name, self.last_name, self.username) + return "%s %s (%s)" % (self.first_name, self.last_name, self.username) else: return self.username -User.__unicode__ = user_unicode +if six.PY2: + User.__unicode__ = user_unicode +else: + User.__str__ = user_unicode class EventRegistrationAdmin(admin.ModelAdmin): form = autocomplete_light.modelform_factory(EventRegistration, exclude=[]) - list_display = ('__unicode__', 'event', 'user', 'paid') + list_display = ('__unicode__' if six.PY2 else '__str__', 'event', 'user', 'paid') list_filter = ('paid',) search_fields = ('user__username', 'user__first_name', 'user__last_name', 'user__email', 'event__title') @@ -206,7 +215,7 @@ class PetitCoursAttributionCounterAdmin(admin.ModelAdmin): def reset(self, request, queryset): queryset.update(count=0) - reset.short_description = u"Remise à zéro du compteur" + reset.short_description = "Remise à zéro du compteur" class PetitCoursDemandeAdmin(admin.ModelAdmin): diff --git a/gestioncof/autocomplete.py b/gestioncof/autocomplete.py index 21b5c3bc..5b4616be 100644 --- a/gestioncof/autocomplete.py +++ b/gestioncof/autocomplete.py @@ -1,3 +1,9 @@ +# -*- coding: utf-8 -*- + +from __future__ import division +from __future__ import print_function +from __future__ import unicode_literals + from django import shortcuts from django.http import Http404 from django.db.models import Q diff --git a/gestioncof/autocomplete_light_registry.py b/gestioncof/autocomplete_light_registry.py index 4a2737cb..f2a2ca6e 100644 --- a/gestioncof/autocomplete_light_registry.py +++ b/gestioncof/autocomplete_light_registry.py @@ -1,3 +1,9 @@ +# -*- coding: utf-8 -*- + +from __future__ import division +from __future__ import print_function +from __future__ import unicode_literals + import autocomplete_light from django.contrib.auth.models import User diff --git a/gestioncof/csv_views.py b/gestioncof/csv_views.py index 733768dc..c1d82aca 100644 --- a/gestioncof/csv_views.py +++ b/gestioncof/csv_views.py @@ -1,3 +1,9 @@ +# -*- coding: utf-8 -*- + +from __future__ import division +from __future__ import print_function +from __future__ import unicode_literals + import csv from django.http import HttpResponse, HttpResponseForbidden from django.template.defaultfilters import slugify diff --git a/gestioncof/decorators.py b/gestioncof/decorators.py index 62c527df..d7e70608 100644 --- a/gestioncof/decorators.py +++ b/gestioncof/decorators.py @@ -1,3 +1,9 @@ +# -*- coding: utf-8 -*- + +from __future__ import division +from __future__ import print_function +from __future__ import unicode_literals + from django_cas_ng.decorators import user_passes_test diff --git a/gestioncof/forms.py b/gestioncof/forms.py index bf983df5..ce3a1b9e 100644 --- a/gestioncof/forms.py +++ b/gestioncof/forms.py @@ -1,4 +1,8 @@ -# coding: utf-8 +# -*- coding: utf-8 -*- + +from __future__ import division +from __future__ import print_function +from __future__ import unicode_literals from django import forms from django.utils.translation import ugettext_lazy as _ @@ -169,8 +173,8 @@ class EventStatusFilterForm(forms.Form): class UserProfileForm(forms.ModelForm): - first_name = forms.CharField(label=_(u'Prénom'), max_length=30) - last_name = forms.CharField(label=_(u'Nom'), max_length=30) + first_name = forms.CharField(label=_('Prénom'), max_length=30) + last_name = forms.CharField(label=_('Nom'), max_length=30) def __init__(self, *args, **kw): super(UserProfileForm, self).__init__(*args, **kw) diff --git a/gestioncof/models.py b/gestioncof/models.py index 540145d5..cf3742f1 100644 --- a/gestioncof/models.py +++ b/gestioncof/models.py @@ -1,53 +1,56 @@ -# coding: utf-8 +# -*- coding: utf-8 -*- + +from __future__ import division +from __future__ import print_function +from __future__ import unicode_literals from django.db import models from django.contrib.auth.models import User from django.utils.translation import ugettext_lazy as _ +from django.utils.encoding import python_2_unicode_compatible +import django.utils.six as six from django.db.models.signals import post_save -from petits_cours_models import * +from gestioncof.petits_cours_models import * 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")), + ('exterieur', _("Extérieur")), + ('1A', _("1A")), + ('2A', _("2A")), + ('3A', _("3A")), + ('4A', _("4A")), + ('archicube', _("Archicube")), + ('doctorant', _("Doctorant")), + ('CST', _("CST")), ) TYPE_COTIZ_CHOICES = ( - ('etudiant', _(u"Normalien étudiant")), - ('normalien', _(u"Normalien élève")), - ('exterieur', _(u"Extérieur")), + ('etudiant', _("Normalien étudiant")), + ('normalien', _("Normalien élève")), + ('exterieur', _("Extérieur")), ) TYPE_COMMENT_FIELD = ( - ('text', _(u"Texte long")), - ('char', _(u"Texte court")), + ('text', _("Texte long")), + ('char', _("Texte court")), ) -def choices_length(choices): - return reduce(lambda m, choice: max(m, len(choice[0])), choices, 0) - - +@python_2_unicode_compatible class CofProfile(models.Model): user = models.OneToOneField(User, related_name="profile") login_clipper = models.CharField("Login clipper", max_length=8, blank=True) is_cof = models.BooleanField("Membre du COF", default=False) num = models.IntegerField("Numéro d'adhérent", blank=True, default=0) phone = models.CharField("Téléphone", max_length=20, blank=True) - occupation = models.CharField(_(u"Occupation"), + occupation = models.CharField(_("Occupation"), default="1A", choices=OCCUPATION_CHOICES, max_length=choices_length( OCCUPATION_CHOICES)) - departement = models.CharField(_(u"Département"), max_length=50, + departement = models.CharField(_("Département"), max_length=50, blank=True) - type_cotiz = models.CharField(_(u"Type de cotisation"), + type_cotiz = models.CharField(_("Type de cotisation"), default="normalien", choices=TYPE_COTIZ_CHOICES, max_length=choices_length( @@ -62,15 +65,15 @@ class CofProfile(models.Model): petits_cours_accept = models.BooleanField( "Recevoir des petits cours", default=False) petits_cours_remarques = models.TextField( - _(u"Remarques et précisions pour les petits cours"), + _("Remarques et précisions pour les petits cours"), blank=True, default="") class Meta: verbose_name = "Profil COF" verbose_name_plural = "Profils COF" - def __unicode__(self): - return unicode(self.user.username) + def __str__(self): + return six.text_type(self.user.username) def create_user_profile(sender, instance, created, **kwargs): @@ -79,13 +82,18 @@ def create_user_profile(sender, instance, created, **kwargs): post_save.connect(create_user_profile, sender=User) +@python_2_unicode_compatible class Club(models.Model): name = models.CharField("Nom", max_length=200) description = models.TextField("Description") respos = models.ManyToManyField(User, related_name="clubs_geres") membres = models.ManyToManyField(User, related_name="clubs") + def __str__(self): + return self.name + +@python_2_unicode_compatible class CustomMail(models.Model): shortname = models.SlugField(max_length=50, blank=False) title = models.CharField("Titre", max_length=200, blank=False) @@ -97,10 +105,11 @@ class CustomMail(models.Model): verbose_name = "Mail personnalisable" verbose_name_plural = "Mails personnalisables" - def __unicode__(self): - return u"%s: %s" % (self.shortname, self.title) + def __str__(self): + return "%s: %s" % (self.shortname, self.title) +@python_2_unicode_compatible class Event(models.Model): title = models.CharField("Titre", max_length=200) location = models.CharField("Lieu", max_length=200) @@ -116,10 +125,11 @@ class Event(models.Model): class Meta: verbose_name = "Événement" - def __unicode__(self): - return unicode(self.title) + def __str__(self): + return six.text_type(self.title) +@python_2_unicode_compatible class EventCommentField(models.Model): event = models.ForeignKey(Event, related_name="commentfields") name = models.CharField("Champ", max_length=200) @@ -130,17 +140,22 @@ class EventCommentField(models.Model): class Meta: verbose_name = "Champ" - def __unicode__(self): - return unicode(self.name) + def __str__(self): + return six.text_type(self.name) +@python_2_unicode_compatible class EventCommentValue(models.Model): commentfield = models.ForeignKey(EventCommentField, related_name="values") registration = models.ForeignKey("EventRegistration", related_name="comments") content = models.TextField("Contenu", blank=True, null=True) + def __str__(self): + return "Commentaire de %s" % self.commentfield + +@python_2_unicode_compatible class EventOption(models.Model): event = models.ForeignKey(Event, related_name="options") name = models.CharField("Option", max_length=200) @@ -149,10 +164,11 @@ class EventOption(models.Model): class Meta: verbose_name = "Option" - def __unicode__(self): - return unicode(self.name) + def __str__(self): + return six.text_type(self.name) +@python_2_unicode_compatible class EventOptionChoice(models.Model): event_option = models.ForeignKey(EventOption, related_name="choices") value = models.CharField("Valeur", max_length=200) @@ -161,10 +177,11 @@ class EventOptionChoice(models.Model): verbose_name = "Choix" verbose_name_plural = "Choix" - def __unicode__(self): - return unicode(self.value) + def __str__(self): + return six.text_type(self.value) +@python_2_unicode_compatible class EventRegistration(models.Model): user = models.ForeignKey(User) event = models.ForeignKey(Event) @@ -177,11 +194,12 @@ class EventRegistration(models.Model): verbose_name = "Inscription" unique_together = ("user", "event") - def __unicode__(self): - return u"Inscription de %s à %s" % (unicode(self.user), - unicode(self.event.title)) + def __str__(self): + return "Inscription de %s à %s" % (six.text_type(self.user), + six.text_type(self.event.title)) +@python_2_unicode_compatible class Survey(models.Model): title = models.CharField("Titre", max_length=200) details = models.TextField("Détails", blank=True) @@ -191,10 +209,11 @@ class Survey(models.Model): class Meta: verbose_name = "Sondage" - def __unicode__(self): - return unicode(self.title) + def __str__(self): + return six.text_type(self.title) +@python_2_unicode_compatible class SurveyQuestion(models.Model): survey = models.ForeignKey(Survey, related_name="questions") question = models.CharField("Question", max_length=200) @@ -203,10 +222,11 @@ class SurveyQuestion(models.Model): class Meta: verbose_name = "Question" - def __unicode__(self): - return unicode(self.question) + def __str__(self): + return six.text_type(self.question) +@python_2_unicode_compatible class SurveyQuestionAnswer(models.Model): survey_question = models.ForeignKey(SurveyQuestion, related_name="answers") answer = models.CharField("Réponse", max_length=200) @@ -214,10 +234,11 @@ class SurveyQuestionAnswer(models.Model): class Meta: verbose_name = "Réponse" - def __unicode__(self): - return unicode(self.answer) + def __str__(self): + return six.text_type(self.answer) +@python_2_unicode_compatible class SurveyAnswer(models.Model): user = models.ForeignKey(User) survey = models.ForeignKey(Survey) @@ -228,7 +249,16 @@ class SurveyAnswer(models.Model): verbose_name = "Réponses" unique_together = ("user", "survey") + def __str__(self): + return "Réponse de %s sondage %s" % ( + self.user.get_full_name(), + self.survey.title) + +@python_2_unicode_compatible class Clipper(models.Model): username = models.CharField("Identifiant", max_length=20) fullname = models.CharField("Nom complet", max_length=200) + + def __str__(self): + return "Clipper %s" % self.username diff --git a/gestioncof/petits_cours_models.py b/gestioncof/petits_cours_models.py index a9aede0c..e9c2943d 100644 --- a/gestioncof/petits_cours_models.py +++ b/gestioncof/petits_cours_models.py @@ -1,25 +1,32 @@ -# coding: utf-8 +# -*- coding: utf-8 -*- + +from __future__ import division +from __future__ import print_function +from __future__ import unicode_literals from django.db import models from django.contrib.auth.models import User from django.utils.translation import ugettext_lazy as _ +from django.utils.encoding import python_2_unicode_compatible +from django.utils.six.moves import reduce def choices_length(choices): return reduce(lambda m, choice: max(m, len(choice[0])), choices, 0) LEVELS_CHOICES = ( - ('college', _(u"Collège")), - ('lycee', _(u"Lycée")), - ('prepa1styear', _(u"Prépa 1ère année / L1")), - ('prepa2ndyear', _(u"Prépa 2ème année / L2")), - ('licence3', _(u"Licence 3")), - ('other', _(u"Autre (préciser dans les commentaires)")), + ('college', _("Collège")), + ('lycee', _("Lycée")), + ('prepa1styear', _("Prépa 1ère année / L1")), + ('prepa2ndyear', _("Prépa 2ème année / L2")), + ('licence3', _("Licence 3")), + ('other', _("Autre (préciser dans les commentaires)")), ) +@python_2_unicode_compatible class PetitCoursSubject(models.Model): - name = models.CharField(_(u"Matière"), max_length=30) + name = models.CharField(_("Matière"), max_length=30) users = models.ManyToManyField(User, related_name="petits_cours_matieres", through="PetitCoursAbility") @@ -27,91 +34,95 @@ class PetitCoursSubject(models.Model): verbose_name = "Matière de petits cours" verbose_name_plural = "Matières des petits cours" - def __unicode__(self): + def __str__(self): return self.name +@python_2_unicode_compatible class PetitCoursAbility(models.Model): user = models.ForeignKey(User) - matiere = models.ForeignKey(PetitCoursSubject, verbose_name=_(u"Matière")) - niveau = models.CharField(_(u"Niveau"), + matiere = models.ForeignKey(PetitCoursSubject, verbose_name=_("Matière")) + niveau = models.CharField(_("Niveau"), choices=LEVELS_CHOICES, max_length=choices_length(LEVELS_CHOICES)) - agrege = models.BooleanField(_(u"Agrégé"), default=False) + agrege = models.BooleanField(_("Agrégé"), default=False) class Meta: verbose_name = "Compétence petits cours" verbose_name_plural = "Compétences des petits cours" - def __unicode__(self): - return u"%s - %s - %s" % (self.user.username, + def __str__(self): + return "%s - %s - %s" % (self.user.username, self.matiere, self.niveau) +@python_2_unicode_compatible class PetitCoursDemande(models.Model): - name = models.CharField(_(u"Nom/prénom"), max_length=200) - email = models.CharField(_(u"Adresse email"), max_length=300) - phone = models.CharField(_(u"Téléphone (facultatif)"), + name = models.CharField(_("Nom/prénom"), max_length=200) + email = models.CharField(_("Adresse email"), max_length=300) + phone = models.CharField(_("Téléphone (facultatif)"), max_length=20, blank=True) quand = models.CharField( - _(u"Quand ?"), - help_text=_(u"Indiquez ici la période désirée pour les petits" + _("Quand ?"), + help_text=_("Indiquez ici la période désirée pour les petits" " cours (vacances scolaires, semaine, week-end)."), max_length=300, blank=True) freq = models.CharField( - _(u"Fréquence"), - help_text=_(u"Indiquez ici la fréquence envisagée " + _("Fréquence"), + help_text=_("Indiquez ici la fréquence envisagée " + "(hebdomadaire, 2 fois par semaine, ...)"), max_length=300, blank=True) lieu = models.CharField( - _(u"Lieu (si préférence)"), - help_text=_(u"Si vous avez avez une préférence sur le lieu."), + _("Lieu (si préférence)"), + help_text=_("Si vous avez avez une préférence sur le lieu."), max_length=300, blank=True) matieres = models.ManyToManyField( - PetitCoursSubject, verbose_name=_(u"Matières"), + PetitCoursSubject, verbose_name=_("Matières"), related_name="demandes") - agrege_requis = models.BooleanField(_(u"Agrégé requis"), default=False) - niveau = models.CharField(_(u"Niveau"), + agrege_requis = models.BooleanField(_("Agrégé requis"), default=False) + niveau = models.CharField(_("Niveau"), default="", choices=LEVELS_CHOICES, max_length=choices_length(LEVELS_CHOICES)) - remarques = models.TextField(_(u"Remarques et précisions"), blank=True) + remarques = models.TextField(_("Remarques et précisions"), blank=True) - traitee = models.BooleanField(_(u"Traitée"), default=False) + traitee = models.BooleanField(_("Traitée"), default=False) traitee_par = models.ForeignKey(User, blank=True, null=True) - processed = models.DateTimeField(_(u"Date de traitement"), + processed = models.DateTimeField(_("Date de traitement"), blank=True, null=True) - created = models.DateTimeField(_(u"Date de création"), auto_now_add=True) + created = models.DateTimeField(_("Date de création"), auto_now_add=True) class Meta: verbose_name = "Demande de petits cours" verbose_name_plural = "Demandes de petits cours" - def __unicode__(self): - return u"Demande %d du %s" % (self.id, - self.created.strftime("%d %b %Y")) + def __str__(self): + return "Demande %d du %s" % (self.id, + self.created.strftime("%d %b %Y")) +@python_2_unicode_compatible class PetitCoursAttribution(models.Model): user = models.ForeignKey(User) demande = models.ForeignKey(PetitCoursDemande, verbose_name=_("Demande")) - matiere = models.ForeignKey(PetitCoursSubject, verbose_name=_(u"Matière")) - date = models.DateTimeField(_(u"Date d'attribution"), auto_now_add=True) + matiere = models.ForeignKey(PetitCoursSubject, verbose_name=_("Matière")) + date = models.DateTimeField(_("Date d'attribution"), auto_now_add=True) rank = models.IntegerField("Rang dans l'email") - selected = models.BooleanField(_(u"Sélectionné par le demandeur"), + selected = models.BooleanField(_("Sélectionné par le demandeur"), default=False) class Meta: verbose_name = "Attribution de petits cours" verbose_name_plural = "Attributions de petits cours" - def __unicode__(self): - return u"Attribution de la demande %d à %s pour %s" \ + def __str__(self): + return "Attribution de la demande %d à %s pour %s" \ % (self.demande.id, self.user.username, self.matiere) +@python_2_unicode_compatible class PetitCoursAttributionCounter(models.Model): user = models.ForeignKey(User) matiere = models.ForeignKey(PetitCoursSubject, verbose_name=_("Matiere")) @@ -121,6 +132,6 @@ class PetitCoursAttributionCounter(models.Model): verbose_name = "Compteur d'attribution de petits cours" verbose_name_plural = "Compteurs d'attributions de petits cours" - def __unicode__(self): - return u"%d demandes envoyées à %s pour %s" \ + def __str__(self): + return "%d demandes envoyées à %s pour %s" \ % (self.count, self.user.username, self.matiere) diff --git a/gestioncof/petits_cours_views.py b/gestioncof/petits_cours_views.py index 2e8c420a..b0f64d37 100644 --- a/gestioncof/petits_cours_views.py +++ b/gestioncof/petits_cours_views.py @@ -1,4 +1,8 @@ -# coding: utf-8 +# -*- coding: utf-8 -*- + +from __future__ import division +from __future__ import print_function +from __future__ import unicode_literals from django.shortcuts import render, get_object_or_404, redirect from django.core import mail @@ -181,12 +185,12 @@ def _traitement_other_preparing(request, demande): if choice == -1: continue if choice not in candidates: - errors.append(u"Choix invalide pour la proposition %d" + errors.append("Choix invalide pour la proposition %d" "en %s" % (choice_id + 1, matiere)) continue user = candidates[choice] if user in proposals[matiere]: - errors.append(u"La proposition %d en %s est un doublon" + errors.append("La proposition %d en %s est un doublon" % (choice_id + 1, matiere)) continue proposals[matiere].append(user) @@ -196,9 +200,9 @@ def _traitement_other_preparing(request, demande): else: proposed_for[user].append(matiere) if not proposals[matiere]: - errors.append(u"Aucune proposition pour %s" % (matiere,)) + errors.append("Aucune proposition pour %s" % (matiere,)) elif len(proposals[matiere]) < 3: - errors.append(u"Seulement %d proposition%s pour %s" + errors.append("Seulement %d proposition%s pour %s" % (len(proposals[matiere]), "s" if len(proposals[matiere]) > 1 else "", matiere)) diff --git a/gestioncof/shared.py b/gestioncof/shared.py index 4fb2e4bc..fc901d50 100644 --- a/gestioncof/shared.py +++ b/gestioncof/shared.py @@ -1,3 +1,9 @@ +# -*- coding: utf-8 -*- + +from __future__ import division +from __future__ import print_function +from __future__ import unicode_literals + from django.contrib.sites.models import Site from django.conf import settings from django_cas_ng.backends import CASBackend diff --git a/gestioncof/templatetags/utils.py b/gestioncof/templatetags/utils.py index 5847f9a6..223f208b 100644 --- a/gestioncof/templatetags/utils.py +++ b/gestioncof/templatetags/utils.py @@ -1,3 +1,9 @@ +# -*- coding: utf-8 -*- + +from __future__ import division +from __future__ import print_function +from __future__ import unicode_literals + from django import template from django.utils.safestring import mark_safe @@ -22,7 +28,7 @@ def highlight_text(text, q): @register.filter def highlight_user(user, q): if user.first_name and user.last_name: - text = u"%s %s (%s)" % (user.first_name, user.last_name, user.username) + text = "%s %s (%s)" % (user.first_name, user.last_name, user.username) else: text = user.username return highlight_text(text, q) @@ -30,7 +36,7 @@ def highlight_user(user, q): @register.filter def highlight_clipper(clipper, q): if clipper.fullname: - text = u"%s (%s)" % (clipper.fullname, clipper.username) + text = "%s (%s)" % (clipper.fullname, clipper.username) else: text = clipper.username return highlight_text(text, q) diff --git a/gestioncof/tests.py b/gestioncof/tests.py index 501deb77..a83ebffc 100644 --- a/gestioncof/tests.py +++ b/gestioncof/tests.py @@ -1,3 +1,4 @@ +# -*- coding: utf-8 -*- """ This file demonstrates writing tests using the unittest module. These will pass when you run "manage.py test". @@ -5,6 +6,10 @@ when you run "manage.py test". Replace this with more appropriate tests for your application. """ +from __future__ import division +from __future__ import print_function +from __future__ import unicode_literals + from django.test import TestCase diff --git a/gestioncof/urls.py b/gestioncof/urls.py index 787dd80f..5cea2f8e 100644 --- a/gestioncof/urls.py +++ b/gestioncof/urls.py @@ -1,3 +1,9 @@ +# -*- coding: utf-8 -*- + +from __future__ import division +from __future__ import print_function +from __future__ import unicode_literals + from django.conf.urls import url from gestioncof.petits_cours_views import DemandeListView diff --git a/gestioncof/views.py b/gestioncof/views.py index 11d15d53..39eba050 100644 --- a/gestioncof/views.py +++ b/gestioncof/views.py @@ -1,4 +1,8 @@ -# coding: utf-8 +# -*- coding: utf-8 -*- + +from __future__ import division +from __future__ import print_function +from __future__ import unicode_literals import unicodecsv @@ -7,6 +11,7 @@ from django.http import Http404, HttpResponse from django.contrib.auth.decorators import login_required from django.contrib.auth.views import login as django_login_view from django.contrib.auth.models import User +import django.utils.six as six from gestioncof.models import Survey, SurveyAnswer, SurveyQuestion, \ SurveyQuestionAnswer @@ -453,13 +458,13 @@ def registration(request): (current_registration, created_reg) = \ EventRegistration.objects.get_or_create(user=member, event=form.event) - update_event_form_comments(event, form, current_registration) + update_event_form_comments(form.event, form, current_registration) current_registration.options = all_choices current_registration.paid = \ (form.cleaned_data['status'] == 'paid') current_registration.save() - if event.title == "Mega 15" and created_reg: - field = EventCommentField.objects.get(event=event, + if form.event.title == "Mega 15" and created_reg: + field = EventCommentField.objects.get(event=form.event, name="Commentaires") try: comments = EventCommentValue.objects.get( @@ -491,7 +496,7 @@ def export_members(request): bits = [profile.num, user.username, user.first_name, user.last_name, user.email, profile.phone, profile.occupation, profile.departement, profile.type_cotiz] - writer.writerow([unicode(bit) for bit in bits]) + writer.writerow([six.text_type(bit) for bit in bits]) return response @@ -511,7 +516,7 @@ def csv_export_mega(filename, qs): profile.phone, profile.num, profile.comments if profile.comments else "", comments] - writer.writerow([unicode(bit) for bit in bits]) + writer.writerow([six.text_type(bit) for bit in bits]) return response @@ -531,7 +536,7 @@ def export_mega_remarksonly(request): profile = user.profile bits = [user.username, user.first_name, user.last_name, user.email, profile.phone, profile.num, profile.comments, val.content] - writer.writerow([unicode(bit) for bit in bits]) + writer.writerow([six.text_type(bit) for bit in bits]) return response diff --git a/gestioncof/widgets.py b/gestioncof/widgets.py index 0f36f202..758fc4ad 100644 --- a/gestioncof/widgets.py +++ b/gestioncof/widgets.py @@ -1,3 +1,9 @@ +# -*- coding: utf-8 -*- + +from __future__ import division +from __future__ import print_function +from __future__ import unicode_literals + from django.forms.widgets import Widget from django.forms.utils import flatatt from django.utils.safestring import mark_safe @@ -15,5 +21,5 @@ class TriStateCheckbox(Widget): if value is None: value = 'none' final_attrs = self.build_attrs(attrs, value=value) - output = [u"" % flatatt(final_attrs)] + output = ["" % flatatt(final_attrs)] return mark_safe('\n'.join(output)) diff --git a/sync_clipper.py b/sync_clipper.py index 4dac6447..d9620b2d 100644 --- a/sync_clipper.py +++ b/sync_clipper.py @@ -1,4 +1,10 @@ #!/usr/bin/env python +# -*- coding: utf-8 -*- + +from __future__ import division +from __future__ import print_function +from __future__ import unicode_literals + import os import sys @@ -7,10 +13,10 @@ if __name__ == "__main__": from gestioncof.models import Clipper current = {} - print "[ FETCHING ]" + print("[ FETCHING ]") for clipper in Clipper.objects.all(): current[clipper.username] = clipper - print "[ SYNCING ]" + print("[ SYNCING ]") for line in sys.stdin: bits = line.split(":") username = bits[0] @@ -20,9 +26,9 @@ if __name__ == "__main__": if clipper.fullname != fullname: clipper.fullname = fullname clipper.save() - print "Updated", username + print("Updated", username) else: clipper = Clipper(username=username, fullname=fullname) clipper.save() - print "Created", username - print "[ DONE ]" + print("Created", username) + print("[ DONE ]")