# coding: utf-8 from __future__ import unicode_literals from django.db import models 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 from django.forms.widgets import DateInput from django.urls import reverse from django.utils import timezone from taggit_autosuggest.managers import TaggableManager from tinymce.models import HTMLField as 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) mail = models.EmailField(u"Adresse e-mail permanente", max_length=200, blank=True) class Meta: verbose_name = u"Profil élève" verbose_name_plural = u"Profils élèves" def __unicode__(self): return u"%s (%s)" % (self.nom, self.user.username) def stages_publics(self): return self.stages.filter(public=True) # 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, created = 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, ('(uid=%s)' % (instance.username,)), [str("cn"), str("mailRoutingAddress"), str("homeDirectory")]) 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[3] dep = dict(DEPARTEMENTS_DEFAUT).get(dep.lower(), '') profil.promotion = u'%s %s' % (dep, annee) pmail = infos.get('mailRoutingAddress', ['%s@clipper.ens.fr'%instance.username]) if len(pmail) > 0: profil.mail = pmail[0] 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, srid = 4326) def __unicode__(self): return u"%s (%s)" % (self.nom, 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): return self.nom # # Un stage # class Stage(models.Model): # Misc auteur = models.ForeignKey(Normalien, related_name="stages") public = models.BooleanField(u"Visible publiquement", default=False) date_creation = models.DateTimeField(u"Créé le", default=timezone.now) date_maj = models.DateTimeField(u"Mis à jour le", default=timezone.now) # 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, verbose_name=u"Matière(s)", related_name="stages") encadrants = models.CharField(u"Encadrant⋅e⋅s", max_length=500, blank=True) structure = models.CharField(u"Structure d'accueil", max_length=500, blank=True) # Avis lieux = models.ManyToManyField(Lieu, related_name="stages", through="AvisLieu", blank=True) @property def avis_lieux(self): return self.avislieu_set.order_by('order') @property def lieu_principal(self): return self.avis_lieux[0].lieu def get_absolute_url(self): return reverse('avisstage:stage', self) def __unicode__(self): return u"%s (par %s)" % (self.sujet, self.auteur.user.username) 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", blank=True) avis_ambiance = RichTextField(u"L'ambiance de travail", blank=True) avis_sujet = RichTextField(u"La mission", blank=True) avis_admin = RichTextField(u"Formalités et administration", blank=True) les_plus = models.TextField(u"Les plus de cette expérience", blank=True) les_moins = models.TextField(u"Les moins de cette expérience", blank=True) def __unicode__(self): return u"Avis sur {%s} par %s" % (self.stage.sujet, self.stage.auteur.user.username) @property def avis_all(self): fields = ['avis_ambiance', 'avis_sujet', 'avis_admin'] return [(AvisStage._meta.get_field(field).verbose_name, getattr(self, field, '')) for field in fields] 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", blank=True) avis_lieustage = RichTextField(u"Le lieu du stage", blank=True) avis_pratique = RichTextField(u"S'installer - conseils pratiques", blank=True) avis_tourisme = RichTextField(u"Dans les parages", blank=True) les_plus = models.TextField(u"Les plus du lieu", blank=True) les_moins = models.TextField(u"Les moins du lieu", blank=True) class Meta: verbose_name = "Avis sur un lieu de stage" verbose_name_plural = "Avis sur un lieu de stage" def __unicode__(self): return u"Avis sur {%s} par %s" % (self.lieu.nom, self.stage.auteur.user_id) @property def avis_all(self): fields = ['avis_lieustage', 'avis_pratique', 'avis_tourisme'] return [(AvisLieu._meta.get_field(field).verbose_name, getattr(self, field, '')) for field in fields]