experiENS/avisstage/models.py

320 lines
11 KiB
Python
Raw Normal View History

2017-04-04 00:28:25 +02:00
# coding: utf-8
2017-04-04 00:31:50 +02:00
from __future__ import unicode_literals
2018-12-28 00:20:14 +01:00
from allauth.account.models import EmailAddress
from allauth.socialaccount.models import SocialAccount
2017-04-04 00:31:50 +02:00
from django.db import models
2017-04-04 00:28:25 +02:00
from django.db.models.signals import post_save
2017-05-02 23:23:26 +02:00
from django.contrib.auth.models import User
2017-04-04 00:28:25 +02:00
from django.contrib.gis.db import models as geomodels
2017-05-02 23:23:26 +02:00
from django.template.defaultfilters import slugify
2017-04-07 03:01:27 +02:00
from django.forms.widgets import DateInput
from django.urls import reverse
2018-12-28 00:20:14 +01:00
2017-04-20 01:53:29 +02:00
from django.utils import timezone
from django.utils.html import strip_tags
2017-04-04 00:28:25 +02:00
2017-05-02 23:23:26 +02:00
from taggit_autosuggest.managers import TaggableManager
2017-04-13 23:40:07 +02:00
from tinymce.models import HTMLField as RichTextField
2017-05-02 23:23:26 +02:00
2017-04-04 00:28:25 +02:00
from .utils import choices_length
2017-05-16 23:37:10 +02:00
from .statics import DEPARTEMENTS_DEFAUT, PAYS_OPTIONS, TYPE_LIEU_OPTIONS, TYPE_STAGE_OPTIONS, TYPE_LIEU_DICT, TYPE_STAGE_DICT, NIVEAU_SCOL_OPTIONS, NIVEAU_SCOL_DICT
2017-04-04 00:28:25 +02:00
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)
2017-05-12 23:29:29 +02:00
contactez_moi = models.BooleanField(u"Inviter les visiteurs à me contacter",
default=True)
bio = models.TextField(u"À propos de moi", blank=True, default="");
2017-04-04 00:28:25 +02:00
class Meta:
verbose_name = u"Profil élève"
verbose_name_plural = u"Profils élèves"
2018-12-26 22:00:36 +01:00
def __str__(self):
return u"%s (%s)" % (self.nom, self.user.username)
2017-04-04 00:28:25 +02:00
2017-05-02 23:23:26 +02:00
# Liste des stages publiés
def stages_publics(self):
2017-05-17 00:10:13 +02:00
return self.stages.filter(public=True).order_by('-date_debut')
2018-12-28 00:20:14 +01:00
@property
def en_scolarite(self):
return SocialAccount.objects.filter(user_id=self.user_id,
provider="clipper").exists()
def has_nonENS_email(self):
a = EmailAddress.objects.filter(user_id=self.user_id,
verified=True) \
.exclude(email__endswith="ens.fr")
print(a)
return a.exists()
2017-04-04 00:28:25 +02:00
# 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:
2017-04-25 23:18:52 +02:00
profil, created = Normalien.objects.get_or_create(user=instance)
2017-04-04 00:28:25 +02:00
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)
2017-05-02 23:23:26 +02:00
l.set_option(ldap.OPT_X_TLS_DEMAND, True)
l.set_option(ldap.OPT_DEBUG_LEVEL, 255)
l.set_option(ldap.OPT_NETWORK_TIMEOUT, 10)
l.set_option(ldap.OPT_TIMEOUT, 10)
2017-04-04 00:28:25 +02:00
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-05-02 23:23:26 +02:00
# Si des informations sont disponibles
2017-04-04 00:28:25 +02:00
if len(info) > 0:
infos = info[0][1]
2017-05-02 23:23:26 +02:00
# Nom
2017-04-04 00:28:25 +02:00
profil.nom = infos.get('cn', [''])[0]
2017-05-02 23:23:26 +02:00
# Parsing du homeDirectory pour la promotion
2017-04-04 00:28:25 +02:00
if 'homeDirectory' in infos:
dirs = infos['homeDirectory'][0].split('/')
if dirs[1] == 'users':
annee = dirs[2]
2017-05-02 03:31:38 +02:00
dep = dirs[3]
dep = dict(DEPARTEMENTS_DEFAUT).get(dep.lower(), '')
2017-04-04 00:28:25 +02:00
profil.promotion = u'%s %s' % (dep, annee)
2017-05-02 23:23:26 +02:00
# Mail
pmail = infos.get('mailRoutingAddress',
2017-05-02 03:31:38 +02:00
['%s@clipper.ens.fr'%instance.username])
2017-04-27 21:42:13 +02:00
if len(pmail) > 0:
profil.mail = pmail[0]
2017-05-02 23:23:26 +02:00
2017-04-04 00:28:25 +02:00
profil.save()
except ldap.LDAPError:
pass
#post_save.connect(create_user_profile, sender=User)
2017-04-04 00:28:25 +02:00
#
# 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)
2017-04-04 00:28:25 +02:00
2017-05-02 23:23:26 +02:00
# Type du lieu en plus joli
@property
def type_lieu_fancy(self):
return TYPE_LIEU_DICT.get(self.type_lieu, ("lieu", False))[0]
2017-05-16 23:37:10 +02:00
2017-05-02 23:23:26 +02:00
@property
def type_lieu_fem(self):
return TYPE_LIEU_DICT.get(self.type_lieu, ("lieu", False))[1]
2017-05-16 23:37:10 +02:00
2018-12-26 22:00:36 +01:00
def __str__(self):
return u"%s (%s)" % (self.nom, self.ville)
2017-04-04 00:28:25 +02:00
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"
2018-12-26 22:00:36 +01:00
def __str__(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)
2017-04-20 01:53:29 +02:00
date_creation = models.DateTimeField(u"Créé le", default=timezone.now)
date_maj = models.DateTimeField(u"Mis à jour le", default=timezone.now)
len_avis_stage = models.IntegerField(u"Longueur des avis de stage", default=0)
len_avis_lieux = models.IntegerField(u"Longueur des avis de lieu", default=0)
2017-04-04 00:28:25 +02:00
# 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))
2017-05-13 00:57:54 +02:00
niveau_scol = models.CharField(u"Année de scolarité",
default="",
choices=NIVEAU_SCOL_OPTIONS,
max_length=choices_length(NIVEAU_SCOL_OPTIONS),
blank=True)
2017-04-04 00:28:25 +02:00
thematiques = TaggableManager(u"Thématiques", blank=True)
2017-04-15 20:03:08 +02:00
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)
2017-04-04 00:28:25 +02:00
# 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
2017-05-02 23:23:26 +02:00
# Affichage des avis ordonnés
2017-04-04 00:28:25 +02:00
@property
def avis_lieux(self):
return self.avislieu_set.order_by('order')
2017-05-02 23:23:26 +02:00
# Shortcut pour affichage rapide
2017-04-04 00:28:25 +02:00
@property
def lieu_principal(self):
2017-05-02 23:23:26 +02:00
avis_lieux = self.avis_lieux
if len(avis_lieux) == 0:
return None
2017-04-04 00:28:25 +02:00
return self.avis_lieux[0].lieu
2017-04-07 03:01:27 +02:00
2017-05-02 23:23:26 +02:00
# Type du stage en plus joli
@property
def type_stage_fancy(self):
return TYPE_STAGE_DICT.get(self.type_stage, ("stage", False))[0]
@property
def type_stage_fem(self):
return TYPE_STAGE_DICT.get(self.type_stage, ("stage", False))[1]
2017-05-16 23:37:10 +02:00
# Niveau scolaire en plus joli
@property
def niveau_scol_fancy(self):
return NIVEAU_SCOL_DICT.get(self.niveau_scol, "")
2017-05-02 23:23:26 +02:00
2017-05-16 23:37:10 +02:00
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
2018-12-26 22:00:36 +01:00
def __str__(self):
return u"%s (par %s)" % (self.sujet, self.auteur.user.username)
2017-04-04 00:28:25 +02:00
def update_stats(self, save=True):
def get_len(obj):
length = 0
avis = obj.avis_all
for k, av in avis:
length += len(av.split())
length += len(obj.chapo.split())
length += len(obj.les_plus.split())
length += len(obj.les_moins.split())
return length
if self.avis_stage:
self.len_avis_stage = get_len(self.avis_stage)
self.len_avis_lieux = 0
for avis in self.avislieu_set.all():
self.len_avis_lieux += get_len(avis)
if save:
self.save()
2017-04-04 00:28:25 +02:00
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)
2017-04-12 00:00:36 +02:00
avis_ambiance = RichTextField(u"L'ambiance de travail", blank=True)
2017-05-02 03:11:34 +02:00
avis_sujet = RichTextField(u"La mission", blank=True)
avis_admin = RichTextField(u"Formalités et administration", blank=True)
avis_prestage = RichTextField(u"Avant le stage", blank=True, default="")
2017-04-04 00:28:25 +02:00
2017-05-02 03:11:34 +02:00
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)
2017-04-04 00:28:25 +02:00
2018-12-26 22:00:36 +01:00
def __str__(self):
2017-04-12 00:00:36 +02:00
return u"Avis sur {%s} par %s" % (self.stage.sujet, self.stage.auteur.user.username)
2017-05-02 23:23:26 +02:00
# Liste des champs d'avis, couplés à leur nom (pour l'affichage)
2017-04-12 00:00:36 +02:00
@property
def avis_all(self):
fields = ['avis_sujet', 'avis_ambiance', 'avis_admin', 'avis_prestage']
2017-04-12 00:00:36 +02:00
return [(AvisStage._meta.get_field(field).verbose_name,
getattr(self, field, '')) for field in fields]
2017-04-04 00:28:25 +02:00
2017-05-02 23:23:26 +02:00
2017-04-04 00:28:25 +02:00
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)
2017-05-02 23:23:26 +02:00
avis_lieustage = RichTextField(u"Les lieux de travail", blank=True)
avis_pratique = RichTextField(u"S'installer - conseils pratiques",
blank=True)
avis_tourisme = RichTextField(u"Dans les parages", blank=True)
2017-04-04 00:28:25 +02:00
les_plus = models.TextField(u"Les plus du lieu", blank=True)
les_moins = models.TextField(u"Les moins du lieu", blank=True)
2017-04-04 00:28:25 +02:00
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
2018-12-26 22:00:36 +01:00
def __str__(self):
return u"Avis sur {%s} par %s" % (self.lieu.nom, self.stage.auteur.user_id)
2017-05-02 23:23:26 +02:00
# Liste des champs d'avis, couplés à leur nom (pour l'affichage)
2017-04-12 00:00:36 +02:00
@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]