From f64a865de1229f6323da538567e69307e1d997a6 Mon Sep 17 00:00:00 2001 From: Hugo Roussille Date: Wed, 15 Mar 2017 07:37:24 +0100 Subject: [PATCH 01/13] =?UTF-8?q?C=C3=B4t=C3=A9=20serveur=20du=20catalogue?= =?UTF-8?q?=20des=20spectacles=20BdA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- bda/urls.py | 2 ++ bda/views.py | 60 +++++++++++++++++++++++++++++++++++++-- provisioning/bootstrap.sh | 1 + 3 files changed, 61 insertions(+), 2 deletions(-) diff --git a/bda/urls.py b/bda/urls.py index bbbf8e39..0af14b53 100644 --- a/bda/urls.py +++ b/bda/urls.py @@ -47,4 +47,6 @@ urlpatterns = [ url(r'^mails-rappel/(?P\d+)$', views.send_rappel), url(r'^descriptions/(?P\d+)$', views.descriptions_spectacles, name='bda-descriptions'), + url(r'^catalogue/(?P[a-z]*)$', views.catalogue, + name='bda-catalogue'), ] diff --git a/bda/views.py b/bda/views.py index 096aacf5..cdc7a296 100644 --- a/bda/views.py +++ b/bda/views.py @@ -3,7 +3,9 @@ import random import hashlib import time +import json from datetime import timedelta +from more_itertools import unique_everseen from custommail.shortcuts import ( send_mass_custom_mail, send_custom_mail, render_custom_mail ) @@ -15,7 +17,7 @@ from django.db import models, transaction from django.core import serializers from django.db.models import Count, Q, Sum from django.forms.models import inlineformset_factory -from django.http import HttpResponseBadRequest, HttpResponseRedirect +from django.http import HttpResponseBadRequest, HttpResponseRedirect, HttpResponse from django.core.urlresolvers import reverse from django.conf import settings from django.utils import timezone, formats @@ -23,7 +25,7 @@ from django.views.generic.list import ListView from gestioncof.decorators import cof_required, buro_required from bda.models import Spectacle, Participant, ChoixSpectacle, Attribution,\ - Tirage, SpectacleRevente + Tirage, SpectacleRevente, Salle from bda.algorithm import Algorithm from bda.forms import BaseBdaFormSet, TokenForm, ResellForm, AnnulForm,\ InscriptionReventeForm, SoldForm @@ -639,3 +641,57 @@ def descriptions_spectacles(request, tirage_id): return HttpResponseBadRequest( "La variable GET 'location' doit contenir un entier") return render(request, 'descriptions.html', {'shows': shows_qs.all()}) + +def catalogue(request,request_type): + """ + Vue destinée à communiquer avec un client AJAX, fournissant soit : + - la liste des tirages + - les catégories et salles d'un tirage + - les descriptions d'un tirage (filtrées selon la catégorie et la salle) + """ + if request_type == "list": + # Dans ce cas on retourne la liste des tirages et de leur id sous forme de JSON + data_return = [{'id':tirage.id, 'title':tirage.title} for tirage in Tirage.objects.all()] + return HttpResponse(json.dumps(data_return)) + if request_type == "details": + # Dans ce cas on retourne une liste des catégories et des salles du tirage + try : + tirage_id = request.GET.get('id', '') + tirage = get_object_or_404(Tirage, id=tirage_id) + except: + return HttpResponseBadRequest() + categories = list(unique_everseen([str(spectacle.category) for spectacle in tirage.spectacle_set.all()])) + categories.remove('None') + locations = list(unique_everseen([str(spectacle.location) for spectacle in tirage.spectacle_set.all()])) + data_return = [{'categories':categories, 'locations':locations}] + return HttpResponse(json.dumps(data_return)) + if request_type == "descriptions": + # Ici on retourne les descriptions correspondant à la catégorie et à la salle spécifiées + locations = {} + for salle in Salle.objects.all(): + locations[salle.name] = salle.id + try: + tirage_id = request.GET.get('id', '') + category_name = request.GET.get('category', '') + location_name = request.GET.get('location', '') + tirage = get_object_or_404(Tirage, id=tirage_id) + + shows_qs = tirage.spectacle_set + if category_name: + shows_qs = shows_qs.filter(category__name=category_name) + if location_name: + shows_qs = shows_qs.filter(location__id=locations[location_name]) + except: + return HttpResponseBadRequest("Impossible de trouver des résultats correspondant à ces caractéristiques") + + def getImgUrl(obj): + """ Cette fonction permet de gérer les cas où il n'y a pas d'image """ + try: + return obj.image.url + except: + return '' + + # On convertit les descriptions à envoyer en une liste facilement JSONifiable (il devrait y avoir un moyen plus efficace en redéfinissant le serializer de JSON) + data_return = [{'title': spectacle.title, 'category': str(spectacle.category), 'date': str(spectacle.date), 'location': str(spectacle.location), 'vips': spectacle.vips, 'description': spectacle.description, 'slots_description': spectacle.slots_description, 'image': getImgUrl(spectacle), 'ext_link': spectacle.ext_link, 'price': spectacle.price, 'slots': spectacle.slots} for spectacle in shows_qs.all()] + return HttpResponse(json.dumps(data_return)) + return HttpResponseBadRequest() # Si la requête n'est pas de la forme attendue, on quitte avec une erreur diff --git a/provisioning/bootstrap.sh b/provisioning/bootstrap.sh index 269e4f25..a08d9282 100644 --- a/provisioning/bootstrap.sh +++ b/provisioning/bootstrap.sh @@ -11,6 +11,7 @@ DBPASSWD="4KZt3nGPLVeWSvtBZPSM3fSzXpzEU4" apt-get update && apt-get install -y python3-pip python3-dev python3-venv \ libmysqlclient-dev libjpeg-dev git redis-server pip install -U pip +pip install more_itertools # Configuration et installation de mysql. Le mot de passe root est le même que # le mot de passe pour l'utilisateur local - pour rappel, ceci est une instance From 68334e15d72abb9bec96d1a08928752dbcc3767f Mon Sep 17 00:00:00 2001 From: Hugo Roussille Date: Thu, 16 Mar 2017 05:50:02 +0100 Subject: [PATCH 02/13] Gestion des citations --- bda/views.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/bda/views.py b/bda/views.py index cdc7a296..31ac3296 100644 --- a/bda/views.py +++ b/bda/views.py @@ -25,7 +25,7 @@ from django.views.generic.list import ListView from gestioncof.decorators import cof_required, buro_required from bda.models import Spectacle, Participant, ChoixSpectacle, Attribution,\ - Tirage, SpectacleRevente, Salle + Tirage, SpectacleRevente, Salle, Quote from bda.algorithm import Algorithm from bda.forms import BaseBdaFormSet, TokenForm, ResellForm, AnnulForm,\ InscriptionReventeForm, SoldForm @@ -691,7 +691,9 @@ def catalogue(request,request_type): except: return '' + specquotes = lambda spectacle: [{'author': str(quote.author), 'text': str(quote.text)} for quote in Quote.objects.filter(spectacle = spectacle).all()] + # On convertit les descriptions à envoyer en une liste facilement JSONifiable (il devrait y avoir un moyen plus efficace en redéfinissant le serializer de JSON) - data_return = [{'title': spectacle.title, 'category': str(spectacle.category), 'date': str(spectacle.date), 'location': str(spectacle.location), 'vips': spectacle.vips, 'description': spectacle.description, 'slots_description': spectacle.slots_description, 'image': getImgUrl(spectacle), 'ext_link': spectacle.ext_link, 'price': spectacle.price, 'slots': spectacle.slots} for spectacle in shows_qs.all()] + data_return = [{'title': spectacle.title, 'category': str(spectacle.category), 'date': str(spectacle.date), 'location': str(spectacle.location), 'vips': spectacle.vips, 'description': spectacle.description, 'slots_description': spectacle.slots_description, 'quotes': specquotes(spectacle),'image': getImgUrl(spectacle), 'ext_link': spectacle.ext_link, 'price': spectacle.price, 'slots': spectacle.slots} for spectacle in shows_qs.all()] return HttpResponse(json.dumps(data_return)) return HttpResponseBadRequest() # Si la requête n'est pas de la forme attendue, on quitte avec une erreur From 7ecea0e391b5a2ee0b5c54289b66dae7237d0552 Mon Sep 17 00:00:00 2001 From: Hugo Roussille Date: Thu, 16 Mar 2017 06:22:01 +0100 Subject: [PATCH 03/13] Meilleure gestion des dates et timezones --- bda/views.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bda/views.py b/bda/views.py index 31ac3296..bcbaaecb 100644 --- a/bda/views.py +++ b/bda/views.py @@ -694,6 +694,6 @@ def catalogue(request,request_type): specquotes = lambda spectacle: [{'author': str(quote.author), 'text': str(quote.text)} for quote in Quote.objects.filter(spectacle = spectacle).all()] # On convertit les descriptions à envoyer en une liste facilement JSONifiable (il devrait y avoir un moyen plus efficace en redéfinissant le serializer de JSON) - data_return = [{'title': spectacle.title, 'category': str(spectacle.category), 'date': str(spectacle.date), 'location': str(spectacle.location), 'vips': spectacle.vips, 'description': spectacle.description, 'slots_description': spectacle.slots_description, 'quotes': specquotes(spectacle),'image': getImgUrl(spectacle), 'ext_link': spectacle.ext_link, 'price': spectacle.price, 'slots': spectacle.slots} for spectacle in shows_qs.all()] + data_return = [{'title': spectacle.title, 'category': str(spectacle.category), 'date': str(formats.date_format(timezone.localtime(spectacle.date), "SHORT_DATETIME_FORMAT")), 'location': str(spectacle.location), 'vips': spectacle.vips, 'description': spectacle.description, 'slots_description': spectacle.slots_description, 'quotes': specquotes(spectacle),'image': getImgUrl(spectacle), 'ext_link': spectacle.ext_link, 'price': spectacle.price, 'slots': spectacle.slots} for spectacle in shows_qs.all()] return HttpResponse(json.dumps(data_return)) return HttpResponseBadRequest() # Si la requête n'est pas de la forme attendue, on quitte avec une erreur From a8428f1b41544c1c2a1979de986240affd026dd5 Mon Sep 17 00:00:00 2001 From: Hugo Roussille Date: Thu, 16 Mar 2017 06:34:49 +0100 Subject: [PATCH 04/13] =?UTF-8?q?Pr=C3=A9cision=20des=20tirages=20qui=20do?= =?UTF-8?q?ivent=20appara=C3=AEtre=20dans=20le=20catalogue?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- bda/models.py | 1 + bda/views.py | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/bda/models.py b/bda/models.py index a405a665..d60c3c94 100644 --- a/bda/models.py +++ b/bda/models.py @@ -18,6 +18,7 @@ class Tirage(models.Model): fermeture = models.DateTimeField("Date et heure de fermerture du tirage") tokens = models.TextField("Graine(s) du tirage", blank=True) active = models.BooleanField("Tirage actif", default=False) + appear_catalogue = models.BooleanField("Tirage à afficher dans le catalogue", default=False) enable_do_tirage = models.BooleanField("Le tirage peut être lancé", default=False) diff --git a/bda/views.py b/bda/views.py index bcbaaecb..34733bec 100644 --- a/bda/views.py +++ b/bda/views.py @@ -651,7 +651,7 @@ def catalogue(request,request_type): """ if request_type == "list": # Dans ce cas on retourne la liste des tirages et de leur id sous forme de JSON - data_return = [{'id':tirage.id, 'title':tirage.title} for tirage in Tirage.objects.all()] + data_return = [{'id':tirage.id, 'title':tirage.title} for tirage in Tirage.objects.filter(appear_catalogue = True).all()] return HttpResponse(json.dumps(data_return)) if request_type == "details": # Dans ce cas on retourne une liste des catégories et des salles du tirage From c4a3c1a92ae27e1f4be6d70790cd515b4a163bbc Mon Sep 17 00:00:00 2001 From: Hugo Roussille Date: Fri, 31 Mar 2017 02:51:58 +0200 Subject: [PATCH 05/13] Formatage du code selon PEP-8 --- bda/views.py | 77 +++++++++++++++++++++++++++++++++++++++------------- 1 file changed, 58 insertions(+), 19 deletions(-) diff --git a/bda/views.py b/bda/views.py index 34733bec..ab12dfa9 100644 --- a/bda/views.py +++ b/bda/views.py @@ -5,11 +5,10 @@ import hashlib import time import json from datetime import timedelta -from more_itertools import unique_everseen from custommail.shortcuts import ( send_mass_custom_mail, send_custom_mail, render_custom_mail ) - +from more_itertools import unique_everseen from django.shortcuts import render, get_object_or_404 from django.contrib.auth.decorators import login_required from django.contrib import messages @@ -17,7 +16,8 @@ from django.db import models, transaction from django.core import serializers from django.db.models import Count, Q, Sum from django.forms.models import inlineformset_factory -from django.http import HttpResponseBadRequest, HttpResponseRedirect, HttpResponse +from django.http import HttpResponseBadRequest, HttpResponseRedirect,\ + HttpResponse from django.core.urlresolvers import reverse from django.conf import settings from django.utils import timezone, formats @@ -642,7 +642,8 @@ def descriptions_spectacles(request, tirage_id): "La variable GET 'location' doit contenir un entier") return render(request, 'descriptions.html', {'shows': shows_qs.all()}) -def catalogue(request,request_type): + +def catalogue(request, request_type): """ Vue destinée à communiquer avec un client AJAX, fournissant soit : - la liste des tirages @@ -650,23 +651,33 @@ def catalogue(request,request_type): - les descriptions d'un tirage (filtrées selon la catégorie et la salle) """ if request_type == "list": - # Dans ce cas on retourne la liste des tirages et de leur id sous forme de JSON - data_return = [{'id':tirage.id, 'title':tirage.title} for tirage in Tirage.objects.filter(appear_catalogue = True).all()] + # Dans ce cas on retourne la liste des tirages et de leur id en JSON + data_return = [ + {'id': tirage.id, 'title': tirage.title} + for tirage in Tirage.objects.filter(appear_catalogue=True).all() + ] return HttpResponse(json.dumps(data_return)) if request_type == "details": - # Dans ce cas on retourne une liste des catégories et des salles du tirage - try : + # Dans ce cas on retourne une liste des catégories et des salles + try: tirage_id = request.GET.get('id', '') tirage = get_object_or_404(Tirage, id=tirage_id) except: return HttpResponseBadRequest() - categories = list(unique_everseen([str(spectacle.category) for spectacle in tirage.spectacle_set.all()])) + categories = list(unique_everseen([ + str(spectacle.category) + for spectacle in tirage.spectacle_set.all() + ])) categories.remove('None') - locations = list(unique_everseen([str(spectacle.location) for spectacle in tirage.spectacle_set.all()])) - data_return = [{'categories':categories, 'locations':locations}] + locations = list(unique_everseen([ + str(spectacle.location) + for spectacle in tirage.spectacle_set.all() + ])) + data_return = [{'categories': categories, 'locations': locations}] return HttpResponse(json.dumps(data_return)) if request_type == "descriptions": - # Ici on retourne les descriptions correspondant à la catégorie et à la salle spécifiées + # Ici on retourne les descriptions correspondant à la catégorie et + # à la salle spécifiées locations = {} for salle in Salle.objects.all(): locations[salle.name] = salle.id @@ -680,20 +691,48 @@ def catalogue(request,request_type): if category_name: shows_qs = shows_qs.filter(category__name=category_name) if location_name: - shows_qs = shows_qs.filter(location__id=locations[location_name]) + shows_qs = shows_qs.filter( + location__id=locations[location_name]) except: - return HttpResponseBadRequest("Impossible de trouver des résultats correspondant à ces caractéristiques") + return HttpResponseBadRequest( + "Impossible de trouver des résultats correspondant \ + à ces caractéristiques") def getImgUrl(obj): - """ Cette fonction permet de gérer les cas où il n'y a pas d'image """ + """ + Cette fonction permet de gérer les cas où il n'y a pas d'image + """ try: return obj.image.url except: return '' - specquotes = lambda spectacle: [{'author': str(quote.author), 'text': str(quote.text)} for quote in Quote.objects.filter(spectacle = spectacle).all()] + def specquotes(spectacle): [ + {'author': str(quote.author), 'text': str(quote.text)} + for quote in Quote.objects.filter(spectacle = spectacle).all() + ] - # On convertit les descriptions à envoyer en une liste facilement JSONifiable (il devrait y avoir un moyen plus efficace en redéfinissant le serializer de JSON) - data_return = [{'title': spectacle.title, 'category': str(spectacle.category), 'date': str(formats.date_format(timezone.localtime(spectacle.date), "SHORT_DATETIME_FORMAT")), 'location': str(spectacle.location), 'vips': spectacle.vips, 'description': spectacle.description, 'slots_description': spectacle.slots_description, 'quotes': specquotes(spectacle),'image': getImgUrl(spectacle), 'ext_link': spectacle.ext_link, 'price': spectacle.price, 'slots': spectacle.slots} for spectacle in shows_qs.all()] + # On convertit les descriptions à envoyer en une liste facilement + # JSONifiable (il devrait y avoir un moyen plus efficace en + # redéfinissant le serializer de JSON) + data_return = [{ + 'title': spectacle.title, + 'category': str(spectacle.category), + 'date': str(formats.date_format( + timezone.localtime(spectacle.date), + "SHORT_DATETIME_FORMAT")), + 'location': str(spectacle.location), + 'vips': spectacle.vips, + 'description': spectacle.description, + 'slots_description': spectacle.slots_description, + 'quotes': specquotes(spectacle), + 'image': getImgUrl(spectacle), + 'ext_link': spectacle.ext_link, + 'price': spectacle.price, + 'slots': spectacle.slots + } + for spectacle in shows_qs.all() + ] return HttpResponse(json.dumps(data_return)) - return HttpResponseBadRequest() # Si la requête n'est pas de la forme attendue, on quitte avec une erreur + # Si la requête n'est pas de la forme attendue, on quitte avec une erreur + return HttpResponseBadRequest() From a9c8de7544740f222bea039b5af6ead2cfa70f39 Mon Sep 17 00:00:00 2001 From: Hugo Roussille Date: Fri, 31 Mar 2017 03:15:40 +0200 Subject: [PATCH 06/13] Utilisation des JsonResponse --- bda/views.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/bda/views.py b/bda/views.py index ab12dfa9..0f9447ff 100644 --- a/bda/views.py +++ b/bda/views.py @@ -17,7 +17,7 @@ from django.core import serializers from django.db.models import Count, Q, Sum from django.forms.models import inlineformset_factory from django.http import HttpResponseBadRequest, HttpResponseRedirect,\ - HttpResponse + JsonResponse, HttpResponse from django.core.urlresolvers import reverse from django.conf import settings from django.utils import timezone, formats @@ -656,7 +656,7 @@ def catalogue(request, request_type): {'id': tirage.id, 'title': tirage.title} for tirage in Tirage.objects.filter(appear_catalogue=True).all() ] - return HttpResponse(json.dumps(data_return)) + return JsonResponse(data_return, safe=False) if request_type == "details": # Dans ce cas on retourne une liste des catégories et des salles try: @@ -674,7 +674,7 @@ def catalogue(request, request_type): for spectacle in tirage.spectacle_set.all() ])) data_return = [{'categories': categories, 'locations': locations}] - return HttpResponse(json.dumps(data_return)) + return JsonResponse(data_return, safe=False) if request_type == "descriptions": # Ici on retourne les descriptions correspondant à la catégorie et # à la salle spécifiées @@ -733,6 +733,6 @@ def catalogue(request, request_type): } for spectacle in shows_qs.all() ] - return HttpResponse(json.dumps(data_return)) + return JsonResponse(data_return, safe=False) # Si la requête n'est pas de la forme attendue, on quitte avec une erreur return HttpResponseBadRequest() From f3b9266e359d5a39a656ec4e2fce1a4f5907e6c3 Mon Sep 17 00:00:00 2001 From: Hugo Roussille Date: Fri, 31 Mar 2017 03:35:09 +0200 Subject: [PATCH 07/13] =?UTF-8?q?Simplification=20du=20code=20avec=20des?= =?UTF-8?q?=20m=C3=A9thodes=20de=20Django?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- bda/views.py | 37 ++++++++++++++----------------------- provisioning/bootstrap.sh | 1 - 2 files changed, 14 insertions(+), 24 deletions(-) diff --git a/bda/views.py b/bda/views.py index 0f9447ff..95429a25 100644 --- a/bda/views.py +++ b/bda/views.py @@ -3,12 +3,10 @@ import random import hashlib import time -import json from datetime import timedelta from custommail.shortcuts import ( send_mass_custom_mail, send_custom_mail, render_custom_mail ) -from more_itertools import unique_everseen from django.shortcuts import render, get_object_or_404 from django.contrib.auth.decorators import login_required from django.contrib import messages @@ -17,7 +15,7 @@ from django.core import serializers from django.db.models import Count, Q, Sum from django.forms.models import inlineformset_factory from django.http import HttpResponseBadRequest, HttpResponseRedirect,\ - JsonResponse, HttpResponse + JsonResponse from django.core.urlresolvers import reverse from django.conf import settings from django.utils import timezone, formats @@ -25,7 +23,7 @@ from django.views.generic.list import ListView from gestioncof.decorators import cof_required, buro_required from bda.models import Spectacle, Participant, ChoixSpectacle, Attribution,\ - Tirage, SpectacleRevente, Salle, Quote + Tirage, SpectacleRevente, Salle, Quote, CategorieSpectacle from bda.algorithm import Algorithm from bda.forms import BaseBdaFormSet, TokenForm, ResellForm, AnnulForm,\ InscriptionReventeForm, SoldForm @@ -652,10 +650,8 @@ def catalogue(request, request_type): """ if request_type == "list": # Dans ce cas on retourne la liste des tirages et de leur id en JSON - data_return = [ - {'id': tirage.id, 'title': tirage.title} - for tirage in Tirage.objects.filter(appear_catalogue=True).all() - ] + data_return = list( + Tirage.objects.filter(appear_catalogue=True).values('id', 'title')) return JsonResponse(data_return, safe=False) if request_type == "details": # Dans ce cas on retourne une liste des catégories et des salles @@ -664,15 +660,14 @@ def catalogue(request, request_type): tirage = get_object_or_404(Tirage, id=tirage_id) except: return HttpResponseBadRequest() - categories = list(unique_everseen([ - str(spectacle.category) - for spectacle in tirage.spectacle_set.all() - ])) - categories.remove('None') - locations = list(unique_everseen([ - str(spectacle.location) - for spectacle in tirage.spectacle_set.all() - ])) + categories = list( + CategorieSpectacle.objects.filter( + spectacle__in=tirage.spectacle_set.all()) + .distinct()) + locations = list( + Salle.objects.filter( + spectacle__in=tirage.spectacle_set.all()) + .distinct().values_list('name', flat=True)) data_return = [{'categories': categories, 'locations': locations}] return JsonResponse(data_return, safe=False) if request_type == "descriptions": @@ -707,11 +702,6 @@ def catalogue(request, request_type): except: return '' - def specquotes(spectacle): [ - {'author': str(quote.author), 'text': str(quote.text)} - for quote in Quote.objects.filter(spectacle = spectacle).all() - ] - # On convertit les descriptions à envoyer en une liste facilement # JSONifiable (il devrait y avoir un moyen plus efficace en # redéfinissant le serializer de JSON) @@ -725,7 +715,8 @@ def catalogue(request, request_type): 'vips': spectacle.vips, 'description': spectacle.description, 'slots_description': spectacle.slots_description, - 'quotes': specquotes(spectacle), + 'quotes': list(Quote.objects.filter(spectacle=spectacle).values( + 'author', 'text')), 'image': getImgUrl(spectacle), 'ext_link': spectacle.ext_link, 'price': spectacle.price, diff --git a/provisioning/bootstrap.sh b/provisioning/bootstrap.sh index a08d9282..269e4f25 100644 --- a/provisioning/bootstrap.sh +++ b/provisioning/bootstrap.sh @@ -11,7 +11,6 @@ DBPASSWD="4KZt3nGPLVeWSvtBZPSM3fSzXpzEU4" apt-get update && apt-get install -y python3-pip python3-dev python3-venv \ libmysqlclient-dev libjpeg-dev git redis-server pip install -U pip -pip install more_itertools # Configuration et installation de mysql. Le mot de passe root est le même que # le mot de passe pour l'utilisateur local - pour rappel, ceci est une instance From 73c21d83ee91507c9c3ba30086314310bd60af4b Mon Sep 17 00:00:00 2001 From: Hugo Roussille Date: Fri, 31 Mar 2017 03:47:32 +0200 Subject: [PATCH 08/13] Correction des exceptions et de l'URL des images --- bda/models.py | 9 +++++++++ bda/views.py | 16 ++++------------ 2 files changed, 13 insertions(+), 12 deletions(-) diff --git a/bda/models.py b/bda/models.py index d60c3c94..04b6d877 100644 --- a/bda/models.py +++ b/bda/models.py @@ -79,6 +79,15 @@ class Spectacle(models.Model): self.price ) + def getImgUrl(self): + """ + Cette fonction permet d'obtenir l'URL de l'image, si elle existe + """ + try: + return self.image.url + except: + return None + def send_rappel(self): """ Envoie un mail de rappel à toutes les personnes qui ont une place pour diff --git a/bda/views.py b/bda/views.py index 95429a25..486de3f2 100644 --- a/bda/views.py +++ b/bda/views.py @@ -658,8 +658,8 @@ def catalogue(request, request_type): try: tirage_id = request.GET.get('id', '') tirage = get_object_or_404(Tirage, id=tirage_id) - except: - return HttpResponseBadRequest() + except ValueError: + return HttpResponseBadRequest("Pas de tirage pour cet id") categories = list( CategorieSpectacle.objects.filter( spectacle__in=tirage.spectacle_set.all()) @@ -688,19 +688,11 @@ def catalogue(request, request_type): if location_name: shows_qs = shows_qs.filter( location__id=locations[location_name]) - except: + except ValueError: return HttpResponseBadRequest( "Impossible de trouver des résultats correspondant \ à ces caractéristiques") - def getImgUrl(obj): - """ - Cette fonction permet de gérer les cas où il n'y a pas d'image - """ - try: - return obj.image.url - except: - return '' # On convertit les descriptions à envoyer en une liste facilement # JSONifiable (il devrait y avoir un moyen plus efficace en @@ -717,7 +709,7 @@ def catalogue(request, request_type): 'slots_description': spectacle.slots_description, 'quotes': list(Quote.objects.filter(spectacle=spectacle).values( 'author', 'text')), - 'image': getImgUrl(spectacle), + 'image': spectacle.getImgUrl(), 'ext_link': spectacle.ext_link, 'price': spectacle.price, 'slots': spectacle.slots From 8cf14d3f6b4e835f0c899c00ee640caa417cc5cf Mon Sep 17 00:00:00 2001 From: Hugo Roussille Date: Fri, 31 Mar 2017 04:33:13 +0200 Subject: [PATCH 09/13] =?UTF-8?q?Possibilit=C3=A9=20de=20filtrer=20sur=20p?= =?UTF-8?q?lusieurs=20salles/cat=C3=A9gories?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- bda/views.py | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/bda/views.py b/bda/views.py index 486de3f2..cee53085 100644 --- a/bda/views.py +++ b/bda/views.py @@ -3,6 +3,7 @@ import random import hashlib import time +import json from datetime import timedelta from custommail.shortcuts import ( send_mass_custom_mail, send_custom_mail, render_custom_mail @@ -663,31 +664,30 @@ def catalogue(request, request_type): categories = list( CategorieSpectacle.objects.filter( spectacle__in=tirage.spectacle_set.all()) - .distinct()) + .distinct().values('id', 'name')) locations = list( Salle.objects.filter( spectacle__in=tirage.spectacle_set.all()) - .distinct().values_list('name', flat=True)) - data_return = [{'categories': categories, 'locations': locations}] + .distinct().values('id', 'name')) + data_return = {'categories': categories, 'locations': locations} return JsonResponse(data_return, safe=False) if request_type == "descriptions": # Ici on retourne les descriptions correspondant à la catégorie et # à la salle spécifiées - locations = {} - for salle in Salle.objects.all(): - locations[salle.name] = salle.id + try: tirage_id = request.GET.get('id', '') - category_name = request.GET.get('category', '') - location_name = request.GET.get('location', '') + category_id = json.loads(request.GET.get('category', '[0]')) + location_id = json.loads(request.GET.get('location', '[0]')) tirage = get_object_or_404(Tirage, id=tirage_id) shows_qs = tirage.spectacle_set - if category_name: - shows_qs = shows_qs.filter(category__name=category_name) - if location_name: + if not(0 in category_id): shows_qs = shows_qs.filter( - location__id=locations[location_name]) + category__id__in=category_id) + if not(0 in location_id): + shows_qs = shows_qs.filter( + location__id__in=location_id) except ValueError: return HttpResponseBadRequest( "Impossible de trouver des résultats correspondant \ From 8a1af73ee0c775fb33c61f8aa30021ad38416a15 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20P=C3=A9pin?= Date: Fri, 31 Mar 2017 17:53:35 +0100 Subject: [PATCH 10/13] A migration for the new field `appear_catalogue` --- .../0011_tirage_appear_catalogue.py | 22 +++++++++++++++++++ 1 file changed, 22 insertions(+) create mode 100644 bda/migrations/0011_tirage_appear_catalogue.py diff --git a/bda/migrations/0011_tirage_appear_catalogue.py b/bda/migrations/0011_tirage_appear_catalogue.py new file mode 100644 index 00000000..c2a2479d --- /dev/null +++ b/bda/migrations/0011_tirage_appear_catalogue.py @@ -0,0 +1,22 @@ +# -*- coding: utf-8 -*- +from __future__ import unicode_literals + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('bda', '0010_spectaclerevente_shotgun'), + ] + + operations = [ + migrations.AddField( + model_name='tirage', + name='appear_catalogue', + field=models.BooleanField( + default=False, + verbose_name='Tirage à afficher dans le catalogue' + ), + ), + ] From 67b44219339d034aa40d8d336f223fd5e63bf8d3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20P=C3=A9pin?= Date: Fri, 31 Mar 2017 17:54:31 +0100 Subject: [PATCH 11/13] PEP8 does not like `\` --- bda/views.py | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/bda/views.py b/bda/views.py index cee53085..dbb3f3c0 100644 --- a/bda/views.py +++ b/bda/views.py @@ -15,19 +15,24 @@ from django.db import models, transaction from django.core import serializers from django.db.models import Count, Q, Sum from django.forms.models import inlineformset_factory -from django.http import HttpResponseBadRequest, HttpResponseRedirect,\ - JsonResponse +from django.http import ( + HttpResponseBadRequest, HttpResponseRedirect, JsonResponse +) from django.core.urlresolvers import reverse from django.conf import settings from django.utils import timezone, formats from django.views.generic.list import ListView from gestioncof.decorators import cof_required, buro_required -from bda.models import Spectacle, Participant, ChoixSpectacle, Attribution,\ - Tirage, SpectacleRevente, Salle, Quote, CategorieSpectacle +from bda.models import ( + Spectacle, Participant, ChoixSpectacle, Attribution, Tirage, + SpectacleRevente, Salle, Quote, CategorieSpectacle +) from bda.algorithm import Algorithm -from bda.forms import BaseBdaFormSet, TokenForm, ResellForm, AnnulForm,\ - InscriptionReventeForm, SoldForm +from bda.forms import ( + BaseBdaFormSet, TokenForm, ResellForm, AnnulForm, InscriptionReventeForm, + SoldForm +) @cof_required @@ -690,9 +695,8 @@ def catalogue(request, request_type): location__id__in=location_id) except ValueError: return HttpResponseBadRequest( - "Impossible de trouver des résultats correspondant \ - à ces caractéristiques") - + "Impossible de trouver des résultats correspondant " + "à ces caractéristiques") # On convertit les descriptions à envoyer en une liste facilement # JSONifiable (il devrait y avoir un moyen plus efficace en From 6b8001db56e3dc209793a843e1eaf2c3e339ceb4 Mon Sep 17 00:00:00 2001 From: Hugo Roussille Date: Sat, 1 Apr 2017 16:34:17 +0200 Subject: [PATCH 12/13] Correction des messages d'erreur et de la gestion des exceptions --- bda/views.py | 37 +++++++++++++++++++++++++++---------- 1 file changed, 27 insertions(+), 10 deletions(-) diff --git a/bda/views.py b/bda/views.py index dbb3f3c0..41e5d08b 100644 --- a/bda/views.py +++ b/bda/views.py @@ -22,7 +22,7 @@ from django.core.urlresolvers import reverse from django.conf import settings from django.utils import timezone, formats from django.views.generic.list import ListView - +from django.core.exceptions import ObjectDoesNotExist from gestioncof.decorators import cof_required, buro_required from bda.models import ( Spectacle, Participant, ChoixSpectacle, Attribution, Tirage, @@ -661,11 +661,17 @@ def catalogue(request, request_type): return JsonResponse(data_return, safe=False) if request_type == "details": # Dans ce cas on retourne une liste des catégories et des salles + tirage_id = request.GET.get('id', '') try: - tirage_id = request.GET.get('id', '') - tirage = get_object_or_404(Tirage, id=tirage_id) + tirage = Tirage.objects.get(id=tirage_id) + except ObjectDoesNotExist: + return HttpResponseBadRequest( + "Aucun tirage correspondant à l'id " + + tirage_id) except ValueError: - return HttpResponseBadRequest("Pas de tirage pour cet id") + return HttpResponseBadRequest( + "Mauvais format d'identifiant : " + + tirage_id) categories = list( CategorieSpectacle.objects.filter( spectacle__in=tirage.spectacle_set.all()) @@ -680,11 +686,13 @@ def catalogue(request, request_type): # Ici on retourne les descriptions correspondant à la catégorie et # à la salle spécifiées + tirage_id = request.GET.get('id', '') + categories = request.GET.get('category', '[0]') + locations = request.GET.get('location', '[0]') try: - tirage_id = request.GET.get('id', '') - category_id = json.loads(request.GET.get('category', '[0]')) - location_id = json.loads(request.GET.get('location', '[0]')) - tirage = get_object_or_404(Tirage, id=tirage_id) + category_id = json.loads(categories) + location_id = json.loads(locations) + tirage = Tirage.objects.get(id=tirage_id) shows_qs = tirage.spectacle_set if not(0 in category_id): @@ -693,10 +701,19 @@ def catalogue(request, request_type): if not(0 in location_id): shows_qs = shows_qs.filter( location__id__in=location_id) - except ValueError: + except ObjectDoesNotExist: return HttpResponseBadRequest( "Impossible de trouver des résultats correspondant " - "à ces caractéristiques") + "à ces caractéristiques : " + + "id = " + tirage_id + + ", catégories = " + categories + + ", salles = " + locations) + except ValueError: # Contient JSONDecodeError + return HttpResponseBadRequest( + "Impossible de parser les paramètres donnés : " + + "id = " + request.GET.get('id', '') + + ", catégories = " + request.GET.get('category', '[0]') + + ", salles = " + request.GET.get('location', '[0]')) # On convertit les descriptions à envoyer en une liste facilement # JSONifiable (il devrait y avoir un moyen plus efficace en From 66dd7848b855d04a1e8e8bd97a844caf5baec5ac Mon Sep 17 00:00:00 2001 From: Hugo Roussille Date: Sat, 1 Apr 2017 16:48:18 +0200 Subject: [PATCH 13/13] Correction du format de l'URL --- bda/urls.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bda/urls.py b/bda/urls.py index 0af14b53..df660740 100644 --- a/bda/urls.py +++ b/bda/urls.py @@ -47,6 +47,6 @@ urlpatterns = [ url(r'^mails-rappel/(?P\d+)$', views.send_rappel), url(r'^descriptions/(?P\d+)$', views.descriptions_spectacles, name='bda-descriptions'), - url(r'^catalogue/(?P[a-z]*)$', views.catalogue, + url(r'^catalogue/(?P[a-z]+)$', views.catalogue, name='bda-catalogue'), ]