2017-04-04 00:28:25 +02:00
|
|
|
# coding: utf-8
|
|
|
|
|
2017-04-04 00:31:50 +02:00
|
|
|
from __future__ import unicode_literals
|
|
|
|
|
|
|
|
from django.db import models
|
2017-04-04 00:28:25 +02:00
|
|
|
from django.contrib.auth.models import User
|
|
|
|
from django.db.models.signals import post_save
|
|
|
|
from django.template.defaultfilters import slugify
|
|
|
|
from django.contrib.gis.db import models as geomodels
|
2017-04-07 03:01:27 +02:00
|
|
|
from django.forms.widgets import DateInput
|
|
|
|
from django.urls import reverse
|
2017-04-04 00:28:25 +02:00
|
|
|
|
2017-04-07 03:01:27 +02:00
|
|
|
from taggit_autosuggest.managers import TaggableManager
|
2017-04-04 00:28:25 +02:00
|
|
|
|
|
|
|
from djrichtextfield.models import RichTextField
|
|
|
|
from .utils import choices_length
|
|
|
|
from .statics import DEPARTEMENTS_DEFAUT, PAYS_OPTIONS, TYPE_LIEU_OPTIONS, TYPE_STAGE_OPTIONS
|
|
|
|
|
|
|
|
import ldap
|
|
|
|
|
|
|
|
#
|
|
|
|
# Profil Normalien (extension du modèle User)
|
|
|
|
#
|
|
|
|
|
|
|
|
class Normalien(models.Model):
|
|
|
|
user = models.OneToOneField(User, related_name="profil")
|
|
|
|
|
|
|
|
# Infos spécifiques
|
|
|
|
nom = models.CharField(u"Nom complet", max_length=255, blank=True)
|
|
|
|
promotion = models.CharField(u"Promotion", max_length=40, blank=True)
|
2017-04-07 03:01:27 +02:00
|
|
|
mail = models.EmailField(u"Adresse e-mail permanente",
|
2017-04-04 00:28:25 +02:00
|
|
|
max_length=200, blank=True)
|
|
|
|
|
|
|
|
class Meta:
|
|
|
|
verbose_name = u"Profil élève"
|
|
|
|
verbose_name_plural = u"Profils élèves"
|
|
|
|
|
|
|
|
def __unicode__(self):
|
|
|
|
return unicode("%s (%s)", self.nom, self.user.username)
|
|
|
|
|
|
|
|
# Hook à la création d'un nouvel utilisateur : récupération de ses infos par LDAP
|
|
|
|
def create_user_profile(sender, instance, created, **kwargs):
|
|
|
|
if created:
|
|
|
|
profil = Normalien.objects.get_or_create(user=instance)
|
|
|
|
try:
|
|
|
|
ldap.set_option(ldap.OPT_X_TLS_REQUIRE_CERT, ldap.OPT_X_TLS_NEVER)
|
|
|
|
l = ldap.initialize("ldaps://ldap.spi.ens.fr:636")
|
|
|
|
l.set_option(ldap.OPT_REFERRALS, 0)
|
|
|
|
l.set_option(ldap.OPT_PROTOCOL_VERSION, 3)
|
|
|
|
l.set_option(ldap.OPT_X_TLS,ldap.OPT_X_TLS_DEMAND)
|
|
|
|
l.set_option( ldap.OPT_X_TLS_DEMAND, True )
|
|
|
|
l.set_option( ldap.OPT_DEBUG_LEVEL, 255 )
|
|
|
|
info = l.search_s('dc=spi,dc=ens,dc=fr',
|
|
|
|
ldap.SCOPE_SUBTREE,
|
2017-04-05 00:23:35 +02:00
|
|
|
('(uid=%s)' % (instance.username,)),
|
|
|
|
[str("cn"),
|
|
|
|
str("mailRoutingAddress"),
|
|
|
|
str("homeDirectory")])
|
2017-04-04 00:28:25 +02:00
|
|
|
if len(info) > 0:
|
|
|
|
infos = info[0][1]
|
|
|
|
profil.nom = infos.get('cn', [''])[0]
|
|
|
|
if 'homeDirectory' in infos:
|
|
|
|
dirs = infos['homeDirectory'][0].split('/')
|
|
|
|
if dirs[1] == 'users':
|
|
|
|
annee = dirs[2]
|
|
|
|
dep = dirs[4]
|
|
|
|
dep = dict(DEPARTEMENTS_DEFAUT).get('dep')
|
|
|
|
profil.promotion = u'%s %s' % (dep, annee)
|
|
|
|
profil.mail = infos.get('mailRoutingAddress',
|
|
|
|
['%s@clipper.ens.fr'%instance.username])
|
|
|
|
profil.save()
|
|
|
|
except ldap.LDAPError:
|
|
|
|
pass
|
|
|
|
post_save.connect(create_user_profile, sender=User)
|
|
|
|
|
|
|
|
#
|
|
|
|
# Lieu de stage
|
|
|
|
#
|
|
|
|
|
|
|
|
class Lieu(models.Model):
|
|
|
|
# Général
|
|
|
|
nom = models.CharField(u"Nom de l'institution d'accueil",
|
|
|
|
max_length=250)
|
|
|
|
type_lieu = models.CharField(u"Type de structure d'accueil",
|
|
|
|
default="universite",
|
|
|
|
choices=TYPE_LIEU_OPTIONS,
|
|
|
|
max_length=choices_length(TYPE_LIEU_OPTIONS))
|
|
|
|
|
|
|
|
# Infos géographiques
|
|
|
|
ville = models.CharField(u"Ville",
|
|
|
|
max_length=200)
|
|
|
|
pays = models.CharField(u"Pays",
|
|
|
|
choices=PAYS_OPTIONS,
|
|
|
|
max_length=choices_length(PAYS_OPTIONS))
|
|
|
|
|
|
|
|
# Coordonnées
|
|
|
|
objects = geomodels.GeoManager() # Requis par GeoDjango
|
|
|
|
coord = geomodels.PointField(u"Coordonnées",
|
|
|
|
geography=True)
|
|
|
|
|
|
|
|
|
|
|
|
def __unicode__(self):
|
|
|
|
return u"%s (%s)" % (self.name, self.ville)
|
|
|
|
|
|
|
|
class Meta:
|
|
|
|
verbose_name = "Lieu"
|
|
|
|
verbose_name_plural = "Lieux"
|
|
|
|
|
|
|
|
#
|
|
|
|
# Matières des stages
|
|
|
|
#
|
|
|
|
|
|
|
|
class StageMatiere(models.Model):
|
|
|
|
nom = models.CharField(u"Nom", max_length=30)
|
|
|
|
slug = models.SlugField()
|
|
|
|
|
|
|
|
class Meta:
|
|
|
|
verbose_name = "Matière des stages"
|
|
|
|
verbose_name_plural = "Matières des stages"
|
|
|
|
|
|
|
|
def __unicode__(self):
|
2017-04-07 03:01:27 +02:00
|
|
|
return self.nom
|
2017-04-04 00:28:25 +02:00
|
|
|
|
|
|
|
#
|
|
|
|
# Un stage
|
|
|
|
#
|
|
|
|
|
|
|
|
class Stage(models.Model):
|
|
|
|
# Misc
|
|
|
|
auteur = models.ForeignKey(Normalien, related_name="stages")
|
|
|
|
public = models.BooleanField(u"Visible publiquement", default=False)
|
|
|
|
|
|
|
|
# Caractéristiques du stage
|
|
|
|
sujet = models.CharField(u"Sujet", max_length=500)
|
|
|
|
|
|
|
|
date_debut = models.DateField(u"Date de début", null=True)
|
|
|
|
date_fin = models.DateField(u"Date de fin", null=True)
|
|
|
|
|
|
|
|
type_stage = models.CharField(u"Type",
|
|
|
|
default="stage",
|
|
|
|
choices=TYPE_STAGE_OPTIONS,
|
|
|
|
max_length=choices_length(TYPE_STAGE_OPTIONS))
|
|
|
|
|
|
|
|
thematiques = TaggableManager(u"Thématiques", blank=True)
|
|
|
|
matieres = models.ManyToManyField(StageMatiere, related_name="stages")
|
|
|
|
encadrants = models.CharField(u"Encadrants", max_length=500, blank=True)
|
|
|
|
|
|
|
|
# Avis
|
|
|
|
lieux = models.ManyToManyField(Lieu, related_name="stages",
|
2017-04-07 03:01:27 +02:00
|
|
|
through="AvisLieu", blank=True)
|
2017-04-04 00:28:25 +02:00
|
|
|
|
|
|
|
@property
|
|
|
|
def avis_lieux(self):
|
|
|
|
return self.avislieu_set.order_by('order')
|
|
|
|
|
|
|
|
@property
|
|
|
|
def lieu_principal(self):
|
|
|
|
return self.avis_lieux[0].lieu
|
2017-04-07 03:01:27 +02:00
|
|
|
|
|
|
|
def get_absolute_url(self):
|
|
|
|
return reverse('avisstage:stage', self)
|
2017-04-04 00:28:25 +02:00
|
|
|
|
|
|
|
def __unicode__(self):
|
|
|
|
return u"%s (par %s)" % (self.sujet, self.auteur.user_id)
|
|
|
|
|
|
|
|
class Meta:
|
|
|
|
verbose_name = "Stage"
|
|
|
|
|
|
|
|
#
|
|
|
|
# Les avis
|
|
|
|
#
|
|
|
|
|
|
|
|
class AvisStage(models.Model):
|
|
|
|
stage = models.OneToOneField(Stage, related_name="avis_stage")
|
|
|
|
|
|
|
|
chapo = models.TextField(u"En quelques mots")
|
|
|
|
avis_personnes = RichTextField(u"Les encadrants et l'équipe")
|
|
|
|
avis_sujet = RichTextField(u"Le sujet de stage")
|
|
|
|
avis_admin = RichTextField(u"Formalités et administration")
|
|
|
|
|
|
|
|
les_plus = models.TextField(u"Les plus du stage")
|
|
|
|
les_moins = models.TextField(u"Les moins du stage")
|
|
|
|
|
|
|
|
def __unicode__(self):
|
|
|
|
return u"Avis sur {%s} par %" % (stage.sujet, stage.auteur.user_id)
|
|
|
|
|
|
|
|
class AvisLieu(models.Model):
|
|
|
|
stage = models.ForeignKey(Stage)
|
|
|
|
lieu = models.ForeignKey(Lieu)
|
|
|
|
order = models.IntegerField("Ordre", default=0)
|
|
|
|
|
|
|
|
chapo = models.TextField(u"En quelques mots")
|
|
|
|
avis_lieustage = RichTextField(u"Le lieu du stage")
|
|
|
|
avis_pratique = RichTextField(u"S'installer - conseils pratiques")
|
|
|
|
avis_tourisme = RichTextField(u"Dans les parages")
|
|
|
|
|
|
|
|
les_plus = models.TextField(u"Les plus du lieu")
|
|
|
|
les_moins = models.TextField(u"Les moins du lieu")
|
|
|
|
|
|
|
|
class Meta:
|
|
|
|
verbose_name = "Avis sur un lieu de stage"
|
|
|
|
verbose_name_plural = "Avis sur un lieu de stage"
|
2017-04-04 00:31:50 +02:00
|
|
|
|
2017-04-04 00:28:25 +02:00
|
|
|
def __unicode__(self):
|
|
|
|
return u"Avis sur {%s} par %" % (lieu.nom, stage.auteur.user_id)
|
|
|
|
|