273 lines
No EOL
11 KiB
Python
273 lines
No EOL
11 KiB
Python
# coding: utf-8
|
|
|
|
from django.shortcuts import get_object_or_404, render
|
|
from django.contrib.auth.decorators import login_required
|
|
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
|
|
from django.contrib.gis import measure
|
|
from django.forms.widgets import HiddenInput
|
|
|
|
from monstage.models import *
|
|
|
|
def addslashes(s):
|
|
d = {'"':'\\"', "'":"\\'", "\0":"\\\0", "\\":"\\\\", '\n':'\\n'}
|
|
return ''.join(d.get(c, c) for c in s)
|
|
|
|
def index(request):
|
|
stats = { 'num_stages': Stage.objects.count() }
|
|
return render(request, 'monstage/index.html', {'stats': stats})
|
|
|
|
def forbidden(request, type):
|
|
context = {}
|
|
context[type] = True
|
|
return render(request, 'monstage/forbidden.html', context)
|
|
|
|
@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)
|
|
lieux_latlng = []
|
|
if not stage.published and not stage.profil_user == request.user.profil:
|
|
return forbidden(request, 'unpublished')
|
|
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),
|
|
'lieux_latlng': lieux_latlng,
|
|
'published':stage.published,
|
|
}
|
|
return render(request, 'monstage/stage.html', context)
|
|
|
|
class StageForm(forms.ModelForm):
|
|
class Meta:
|
|
model = Stage
|
|
fields = ("type_stage", "start_date", "end_date", "matieres", "sujet", "thematiques", "encadrants")
|
|
|
|
@login_required
|
|
def stage_add(request):
|
|
if request.POST:
|
|
form = StageForm(request.POST)
|
|
if form.is_valid:
|
|
new_stage = form.save(commit = False)
|
|
new_stage.profil_user = request.user.profil
|
|
new_stage.save()
|
|
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 })
|
|
|
|
@login_required
|
|
def stage_edit_desc(request, stage_id):
|
|
stage = get_object_or_404( Stage, pk = stage_id)
|
|
if stage.profil_user != request.user.profil:
|
|
return forbidden(request, 'notowned')
|
|
bullshit = ""
|
|
if request.POST:
|
|
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 })
|
|
|
|
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:
|
|
# GEOS Format : (longitude, latitude)
|
|
self.fields['longitude'].initial = lieu.coord.x
|
|
self.fields['latitude'].initial = lieu.coord.y
|
|
|
|
class Meta:
|
|
model = Lieu
|
|
fields = ("name", "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)
|
|
# GEOS Format : (longitude, latitude)
|
|
lieu.coord = GEOSGeometry('POINT(%f %f)' % (self.cleaned_data['longitude'], self.cleaned_data['latitude']), srid=4326)
|
|
return lieu
|
|
|
|
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:
|
|
# GEOS Format : (longitude, latitude)
|
|
coords = GEOSGeometry('POINT(%f %f)' % (lon, lat), srid=4326)
|
|
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 = ''
|
|
if stage.profil_user != request.user.profil:
|
|
return forbidden(request, 'notowned')
|
|
if request.POST:
|
|
valid = True
|
|
prevLieuxStage = [k for k in stage.lieustage_set.all()]
|
|
lieuforms = []
|
|
deleted = []
|
|
for i in range(0, int(request.POST['numplaces'])):
|
|
toSave = False
|
|
if request.POST.get('%d-name' % i, False): # Lieu à créer
|
|
bullshit += str(i) + 'a '
|
|
lieuform = LieuForm(request.POST, prefix = str(i))
|
|
if not lieuform.is_valid():
|
|
valid = False
|
|
lieuforms.append(lieuform)
|
|
continue
|
|
if lieuform.is_to_delete():
|
|
pass
|
|
else:
|
|
lieu = lieuform.save()
|
|
lieu.save()
|
|
lieuform.save_m2m()
|
|
toSave = True
|
|
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
|
|
if lieuform.is_to_delete():
|
|
if len(prevLieuxStage) > 0:
|
|
deleted.append(prevLieuxStage.pop(0))
|
|
else:
|
|
lieuforms.append(lieuform)
|
|
lieu = Lieu.objects.get( pk = lieuform.cleaned_data['lieu_id'] )
|
|
toSave = True
|
|
if toSave: # Mise à jour des liens lieu - stage
|
|
if len(prevLieuxStage) > 0:
|
|
lieustage = prevLieuxStage.pop(0)
|
|
lieustage.lieu = lieu
|
|
lieustage.save()
|
|
elif len(deleted) > 0:
|
|
lieustage = deleted.pop(0)
|
|
lieustage.lieu = lieu
|
|
lieustage.save()
|
|
else:
|
|
LieuStage.objects.create(lieu = lieu, stage = stage)
|
|
if valid:
|
|
for lieustage in deleted:
|
|
lieustage.delete()
|
|
return HttpResponseRedirect(reverse('monstage:stage_edit_feedback', args=(stage.id,)))
|
|
else:
|
|
lieuforms = [(lieu, LieuStageForm(initial={'lieu_id': lieu.id}, prefix=str(counter))) for counter, lieu in enumerate(stage.lieux.all())]
|
|
emptyform = LieuForm(prefix='{{ID}}')
|
|
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) })
|
|
|
|
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:
|
|
return forbidden(request, 'notowned')
|
|
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 })
|
|
|
|
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)
|
|
return render(request, 'monstage/detail.html', {'question': question})
|
|
|
|
|
|
#
|
|
# Recherche de stages
|
|
#
|
|
|
|
def search(request):
|
|
return render(request, 'monstage/search.html') |