experiENS/monstage/views.py

319 lines
14 KiB
Python
Raw Normal View History

2015-06-14 19:13:27 +02:00
# coding: utf-8
from django.shortcuts import get_object_or_404, render
from django.contrib.auth.decorators import login_required
2015-06-14 19:13:27 +02:00
from django.http import HttpResponseRedirect, HttpResponse, HttpResponseForbidden, HttpResponseNotFound
from django.core.urlresolvers import reverse
from django import forms
from django.contrib.gis.geos import GEOSGeometry
2015-06-14 19:13:27 +02:00
from django.contrib.gis import measure
from django.forms.widgets import HiddenInput
from monstage.models import *
def addslashes(s):
2015-08-26 13:58:18 +02:00
d = {'"':'\\"', "\0":"\\\0", "\\":"\\\\", '\n':'\\n'}
return ''.join(d.get(c, c) for c in s)
def index(request):
2015-09-21 19:14:26 +02:00
stats = { 'num_stages': Stage.objects.filter(published=True).count() }
2015-06-20 00:02:36 +02:00
return render(request, 'monstage/index.html', {'stats': stats})
2015-06-22 19:49:12 +02:00
def forbidden(request, type):
context = {}
context[type] = True
return render(request, 'monstage/forbidden.html', context)
2015-06-20 00:02:36 +02:00
@login_required
def home(request):
stages = request.user.profil.stages.all()
return render(request, 'monstage/home.html', {"stages" : stages})
#
# Utilisateurs et profils
#
def profil(request, profil_id):
user = get_object_or_404( User, username = profil_id )
profil = user.profil
stages = Stage.objects.filter( profil_user = profil )
return render(request, 'monstage/profil.html', {'profil': profil, 'stages': stages})
@login_required
def profil_edit(request):
if request.POST:
user = request.user
user.first_name = request.POST['first_name']
user.last_name = request.POST['last_name']
user.save()
return HttpResponseRedirect(reverse('monstage:profil', args=(request.user.username,)))
else:
(profil, _) = Normalien.objects.get_or_create( user = request.user )
return render(request, 'monstage/profil_edit.html', {'normalien': profil})
#
# Stages
#
def stage(request, stage_id):
stage = get_object_or_404( Stage, pk = stage_id)
2015-06-17 00:54:14 +02:00
lieux_latlng = []
2015-06-22 19:49:12 +02:00
if not stage.published and not stage.profil_user == request.user.profil:
return forbidden(request, 'unpublished')
2015-06-17 00:54:14 +02:00
for lieu in stage.lieux.all():
# GEOS Format : (longitude, latitude)
lieux_latlng.append("%f, %f" % (lieu.coord.y, lieu.coord.x))
context = {
'stage': stage,
'modifiable': (stage.profil_user == request.user.profil),
2015-06-22 19:49:12 +02:00
'lieux_latlng': lieux_latlng,
'published':stage.published,
2015-06-17 00:54:14 +02:00
}
return render(request, 'monstage/stage.html', context)
class StageForm(forms.ModelForm):
class Meta:
model = Stage
2015-06-14 23:04:43 +02:00
fields = ("type_stage", "start_date", "end_date", "matieres", "sujet", "thematiques", "encadrants")
2015-09-21 19:34:58 +02:00
def __init__(self, *args, **kwargs):
super(StageForm, self).__init__(*args, **kwargs)
self.fields['matieres'].label = "Matières"
self.fields['thematiques'].help_text = "Une liste de tags séparés par des virgules (ou des espaces)"
self.fields['start_date'].widget.attrs['placeholder'] = "JJ/MM/AAAA"
self.fields['end_date'].widget.attrs['placeholder'] = "JJ/MM/AAAA"
@login_required
def stage_add(request):
if request.POST:
form = StageForm(request.POST)
if form.is_valid:
new_stage = form.save(commit = False)
2015-06-14 23:04:43 +02:00
new_stage.profil_user = request.user.profil
new_stage.save()
2015-06-14 23:04:43 +02:00
form.save_m2m()
return HttpResponseRedirect(reverse('monstage:stage_edit_lieu', args=(new_stage.id,)))
else:
form = StageForm()
return render(request, 'monstage/stage_add.html', { 'form': form })
2015-06-14 23:04:43 +02:00
@login_required
2015-06-13 23:02:16 +02:00
def stage_edit_desc(request, stage_id):
stage = get_object_or_404( Stage, pk = stage_id)
if stage.profil_user != request.user.profil:
2015-06-22 19:49:12 +02:00
return forbidden(request, 'notowned')
2015-06-13 23:02:16 +02:00
bullshit = ""
if request.POST:
2015-06-14 23:04:43 +02:00
form = StageForm(request.POST, instance = stage)
if form.is_valid():
form.save()
return HttpResponseRedirect(reverse('monstage:stage', args=(stage.id,)))
else:
form = StageForm(instance = stage)
return render(request, 'monstage/stage_edit_desc.html', { 'stage': stage, 'form':form })
2015-06-13 23:02:16 +02:00
2015-06-14 19:13:27 +02:00
class LieuStageForm(forms.Form):
lieu_id = forms.IntegerField(widget = HiddenInput())
delete = forms.BooleanField(help_text=(u'Supprimer ce lieu'), required = False, label = '')
def is_to_delete(self):
return self.cleaned_data['delete']
class LieuForm(forms.ModelForm):
latitude = forms.DecimalField()
longitude = forms.DecimalField()
delete = forms.BooleanField(help_text=(u'Supprimer ce lieu'), required = False, label = '')
def __init__(self, *args, **kwargs):
super(LieuForm, self).__init__(*args, **kwargs)
self.fields['latitude'].widget = HiddenInput()
self.fields['longitude'].widget = HiddenInput()
lieu = kwargs.pop('instance', None)
if lieu:
2015-06-17 00:54:14 +02:00
# GEOS Format : (longitude, latitude)
self.fields['longitude'].initial = lieu.coord.x
self.fields['latitude'].initial = lieu.coord.y
class Meta:
model = Lieu
2015-08-26 13:58:18 +02:00
fields = ("name", "type_lieu", "ville", "pays")
def is_to_delete(self):
return self.cleaned_data['delete']
def save(self, *args, **kwargs):
lieu = super(LieuForm, self).save(commit=False, *args, **kwargs)
2015-06-17 00:54:14 +02:00
# GEOS Format : (longitude, latitude)
lieu.coord = GEOSGeometry('POINT(%f %f)' % (self.cleaned_data['longitude'], self.cleaned_data['latitude']), srid=4326)
2015-06-14 23:04:43 +02:00
return lieu
2015-06-14 19:13:27 +02:00
def lieux_candidats(request):
if request.GET:
lat = float(request.GET.get('lat', False))
lon = float(request.GET.get('lon', False))
if lat and lon:
2015-06-17 00:54:14 +02:00
# GEOS Format : (longitude, latitude)
coords = GEOSGeometry('POINT(%f %f)' % (lon, lat), srid=4326)
2015-06-14 19:13:27 +02:00
distance = {'km': 0.5}
lieux = Lieu.objects.filter(coord__distance_lte=(coords, measure.D(**distance)))
lieux = lieux.distance(coords).order_by('distance')
retour = [ {'name': addslashes(lieu.name), 'id': lieu.id, 'lat':str(lieu.coord.coords[0]), 'lon':str(lieu.coord.coords[1]), 'distance':lieu.distance } for lieu in lieux.distance(coords) ]
return render(request, 'monstage/lieux_proches.json', { 'lieux':retour }, content_type='text/plain; charset=utf-8')
return HttpResponseNotFound()
def stage_edit_lieu(request, stage_id):
stage = get_object_or_404( Stage, pk = stage_id)
bullshit = ''
2015-06-13 23:02:16 +02:00
if stage.profil_user != request.user.profil:
2015-06-22 19:49:12 +02:00
return forbidden(request, 'notowned')
if request.POST:
valid = True
2015-06-14 19:13:27 +02:00
prevLieuxStage = [k for k in stage.lieustage_set.all()]
lieuforms = []
deleted = []
2015-08-26 13:58:18 +02:00
for i in range(0, int(request.POST['numplaces'])): # Pour chaque lieu
2015-06-14 23:04:43 +02:00
toSave = False
if request.POST.get('%d-name' % i, False): # Lieu à créer
2015-06-14 19:13:27 +02:00
bullshit += str(i) + 'a '
lieuform = LieuForm(request.POST, prefix = str(i))
if not lieuform.is_valid():
valid = False
lieuforms.append(lieuform)
continue
2015-08-26 13:58:18 +02:00
if lieuform.is_to_delete(): # On ne fait rien : le lieu est nouveau donc n'était pas encore en mémoire
2015-06-14 19:13:27 +02:00
pass
2015-08-26 13:58:18 +02:00
else: # On crée un nouveau lieu
2015-06-14 19:13:27 +02:00
lieu = lieuform.save()
2015-06-14 23:04:43 +02:00
lieu.save()
lieuform.save_m2m()
toSave = True
2015-06-14 19:13:27 +02:00
lieuforms.append(LieuStageForm(initial = {'lieu_id': lieu.id}, prefix = str(i)))
elif request.POST.get('%d-lieu_id' % i, False): # Lien vers un lieu déjà existant
bullshit += str(i) + 'b '
lieuform = LieuStageForm(request.POST, prefix = str(i))
if not lieuform.is_valid():
bullshit += 'invalid '
valid = False
lieuforms.append(lieuform)
continue
2015-08-26 13:58:18 +02:00
if lieuform.is_to_delete(): # On transvase de prevLieuxStage vers deleted pour conserver l'assignation des commentaires
2015-06-14 19:13:27 +02:00
if len(prevLieuxStage) > 0:
deleted.append(prevLieuxStage.pop(0))
2015-08-26 13:58:18 +02:00
else: # On récupère le lieu concerné
2015-06-14 19:13:27 +02:00
lieuforms.append(lieuform)
lieu = Lieu.objects.get( pk = lieuform.cleaned_data['lieu_id'] )
2015-06-14 23:04:43 +02:00
toSave = True
2015-08-26 13:58:18 +02:00
if toSave: # Mise à jour des lieuStage
if len(prevLieuxStage) > 0: # On met à jour un lieuStage conservé (même lieu)
2015-06-14 23:04:43 +02:00
lieustage = prevLieuxStage.pop(0)
lieustage.lieu = lieu
lieustage.save()
2015-08-26 13:58:18 +02:00
elif len(deleted) > 0: # On réutilise l'emplacement d'un lieuStage qui a été supprimé (pour éviter de perdre les commentaires)
2015-06-14 23:04:43 +02:00
lieustage = deleted.pop(0)
lieustage.lieu = lieu
lieustage.save()
2015-08-26 13:58:18 +02:00
else: # On en crée un nouveau
2015-06-14 23:04:43 +02:00
LieuStage.objects.create(lieu = lieu, stage = stage)
2015-06-14 19:13:27 +02:00
if valid:
2015-08-26 13:58:18 +02:00
for lieustage in deleted: # On supprime effectivement les lieuStages non réutilisé
lieustage.delete()
2015-06-14 19:13:27 +02:00
return HttpResponseRedirect(reverse('monstage:stage_edit_feedback', args=(stage.id,)))
else:
2015-06-14 19:13:27 +02:00
lieuforms = [(lieu, LieuStageForm(initial={'lieu_id': lieu.id}, prefix=str(counter))) for counter, lieu in enumerate(stage.lieux.all())]
emptyform = LieuForm(prefix='{{ID}}')
2015-06-14 19:13:27 +02:00
emptylieu = LieuStageForm(prefix='{{ID}}')
return render(request, 'monstage/stage_edit_lieu.html', { 'stage': stage, 'debug': bullshit, 'lieuforms': lieuforms, 'emptyform': addslashes(emptyform.as_p()), 'emptylieu': addslashes(emptylieu.as_p()), 'numforms':len(lieuforms) })
2015-06-13 23:02:16 +02:00
class StageFeedbackForm(forms.ModelForm):
class Meta:
model = Stage
fields = ("avis_encadrants", "avis_equipe", "avis_stage", "avis_admin")
class LieuStageFeedbackForm(forms.ModelForm):
class Meta:
model = LieuStage
fields = ("avis_global", "avis_lieudevie", "avis_lieustage", "avis_pratique", "avis_visite", "avis_anecdotes")
def stage_edit_feedback(request, stage_id):
stage = get_object_or_404( Stage, pk = stage_id)
if stage.profil_user != request.user.profil:
2015-06-22 19:49:12 +02:00
return forbidden(request, 'notowned')
2015-06-13 23:02:16 +02:00
if request.POST:
form_gen = StageFeedbackForm(request.POST, instance = stage, prefix = 'gen')
forms_lieux = [(LieuStageFeedbackForm(request.POST, instance = lieustage, prefix = lieustage.id), lieustage.lieu) for lieustage in stage.lieustage_set.all()]
valid = form_gen.is_valid()
for (form, _) in forms_lieux:
if not form.is_valid():
valid = False
if valid:
form_gen.save()
for (form, _) in forms_lieux:
form.save()
return HttpResponseRedirect(reverse('monstage:stage', args=(stage.id,)))
else:
form_gen = StageFeedbackForm(instance = stage, prefix = 'gen')
forms_lieux = [(LieuStageFeedbackForm(instance = lieustage, prefix = lieustage.id), lieustage.lieu) for lieustage in stage.lieustage_set.all()]
return render(request, 'monstage/stage_edit_feedback.html', { 'stage': stage, 'form_gen':form_gen, 'forms_lieux':forms_lieux })
2015-06-22 19:49:12 +02:00
def stage_publish(request, stage_id):
stage = get_object_or_404( Stage, pk = stage_id)
if request.POST:
publishit = request.POST.get('publishit', False)
if publishit == "yes":
stage.published = True
stage.save()
elif publishit == "no":
stage.published = False
stage.save()
return HttpResponseRedirect(reverse('monstage:stage', args=(stage_id,)))
def detail(request, question_id):
question = get_object_or_404(Question, pk=question_id)
2015-06-20 00:02:36 +02:00
return render(request, 'monstage/detail.html', {'question': question})
#
# Recherche de stages
#
2015-09-16 18:59:39 +02:00
from django.db.models import Q
2015-06-20 00:02:36 +02:00
2015-08-26 13:58:18 +02:00
class SearchForm(forms.Form):
2015-09-21 19:34:58 +02:00
matiere = forms.ModelChoiceField(label='Matière :', required=False, queryset = StageMatiere.objects.all(), empty_label="Toute matière")
2015-08-26 13:58:18 +02:00
thematiques = forms.CharField(label='Thématiques :', required=False)
latitude = forms.DecimalField(widget=HiddenInput(), required=False)
longitude = forms.DecimalField(widget=HiddenInput(), required=False)
lieu = forms.CharField(label=u'A proximité de :', required=False)
2015-09-21 19:34:58 +02:00
tolerance = forms.DecimalField(label='Dans un rayon de (en km) :', initial=100, required=False)
2015-08-26 13:58:18 +02:00
2015-09-21 11:30:41 +02:00
@login_required
2015-06-20 00:02:36 +02:00
def search(request):
2015-08-26 13:58:18 +02:00
stages = None
if request.GET:
form = SearchForm(request.GET)
if form.is_valid():
lon = form.cleaned_data['longitude']
lat = form.cleaned_data['latitude']
2015-09-16 18:59:39 +02:00
lieu = form.cleaned_data['lieu']
2015-09-21 11:30:41 +02:00
stages = Stage.objects.filter(published=True)
2015-09-16 18:59:39 +02:00
if lat and lon and lieu:
2015-08-26 13:58:18 +02:00
coords = GEOSGeometry('POINT(%f %f)' % (lon, lat), srid=4326)
distance = {'km': form.cleaned_data['tolerance']}
lieux = Lieu.objects.filter(coord__distance_lte=(coords, measure.D(**distance)))
lieux = lieux.distance(coords).order_by('distance')
2015-09-16 18:59:39 +02:00
stages = stages.filter(lieux__in=lieux)
2015-08-26 13:58:18 +02:00
matiere = form.cleaned_data['matiere']
if matiere:
2015-09-21 19:34:58 +02:00
stages = stages.filter(matieres=matiere)
2015-09-16 18:59:39 +02:00
thematiques = form.cleaned_data['thematiques'].split(',')
if thematiques:
q = Q()
for thematique in thematiques:
q |= Q(thematiques__name__icontains = thematique)
stages = stages.filter(q).distinct()
2015-08-26 13:58:18 +02:00
stages = stages.all()
else:
form = SearchForm()
return render(request, 'monstage/search.html', {'form':form, 'resultats':stages})