auf.django.emploi
-===================
+=================
+
+0.5
+---
+
+* fix api_emploi
+
+0.4
+---
+
+* refactorisation du code
+
+ - couplage models / form
+
+ - de/serialisation Django des instances de model
+
+ - renommage des variables de conf (voir settings.py)
+
+* ajout des pièces jointes
+
+0.3
+---
+
+* merge de la branche recrutement
+
+0.2
+---
+
+* ajout des dépendances (reskit)
0.1
---
-* Création du module :
+* Création du module
+
+* Les pièces-jointes ne sont pas gérées
+
# -*- encoding: utf-8 -*
+from django.core import serializers
from django.shortcuts import render_to_response, redirect, get_object_or_404
from django.template import Context, RequestContext
-
from django.utils import simplejson
from auf.django.emploi import models as emploi
-from auf.django.emploi import forms as emploiForms
-from restkit import request as req
+from restkit import request, Resource
import datamaster_modeles.models as ref
+import poster
+import urllib2
+from auf.django.emploi import settings
+
+
+STATUS_OK = 200
+
+def req(*args, **kwargs):
+ timeout = 10
+ if not kwargs.has_key('timeout'):
+ kwargs['timeout'] = timeout
+ return request(*args, **kwargs)
class API:
- def __init__(self, request):
+ def __init__(self, request, env):
self.request = request
+ self.env = env
- def offre_emploi_liste(self):
- url = "http://127.0.0.1:8000/api/offre_emploi_liste/"
+ def offre_emploi_liste(self,):
+ url = settings.RECRUTEMENT_URLS[self.env] + "offre_emploi_liste/"
r = req(url)
- liste_json = r.body_string()
- liste_offres = simplejson.loads(liste_json)
- obj_offres_emploi = []
-
- for offre_dict in liste_offres:
- offre = emploi.OffreEmploi()
- offre.est_affiche = offre_dict['est_affiche']
- offre.statut = offre_dict['statut']
- offre.nom = offre_dict['nom']
- offre.resume = offre_dict['resume']
- offre.description = offre_dict['description']
- offre.poste_nom = offre_dict['poste_nom']
- offre.date_limite = offre_dict['date_limite']
- offre.region = ref.Region.objects.get(id=offre_dict['region'])
- offre.bureau = ref.Bureau.objects.get(id=offre_dict['bureau'])
- offre.duree_affectation = offre_dict['duree_affectation']
- offre.renumeration = offre_dict['renumeration']
- offre.debut_affectation = offre_dict['debut_affectation']
- offre.lieu_affectation = ref.Implantation.objects.get(id=offre_dict['lieu_affectation'])
- obj_offres_emploi.append(offre)
- return obj_offres_emploi
+ data = r.body_string()
+ offres = [offre.object for offre in serializers.deserialize("json", data)]
+ return offres
def offre_emploi(self, offre_id):
- url = "http://127.0.0.1:8000/api/offre_emploi/?id=%s"
- r = req(url % (offre_id))
- offre_json = r.body_string()
- offre_dict = simplejson.loads(offre_json)
- obj_offres_emploi = []
-
- offre = emploi.OffreEmploi()
- offre.est_affiche = offre_dict['est_affiche']
- offre.statut = offre_dict['statut']
- offre.nom = offre_dict['nom']
- offre.resume = offre_dict['resume']
- offre.description = offre_dict['description']
- offre.poste_nom = offre_dict['poste_nom']
- offre.date_limite = offre_dict['date_limite']
- offre.region = ref.Region.objects.get(id=offre_dict['region'])
- offre.bureau = ref.Bureau.objects.get(id=offre_dict['bureau'])
- offre.duree_affectation = offre_dict['duree_affectation']
- offre.renumeration = offre_dict['renumeration']
- offre.debut_affectation = offre_dict['debut_affectation']
- offre.lieu_affectation = ref.Implantation.objects.get(id=offre_dict['lieu_affectation'])
- obj_offres_emploi.append(offre)
- return obj_offres_emploi
-
- def candidat_add(self, offre_id):
- url = "http://127.0.0.1:8000/api/candidat_add/?id=%s" % (offre_id)
- return redirect(url)
-
-
+ url = settings.RECRUTEMENT_URLS[self.env] + "offre_emploi/?id=%s"
+ r = req(url % offre_id)
+ data = r.body_string()
+ offres = [o.object for o in serializers.deserialize("json", data)]
+ if len(offres) == 0:
+ return offres[0]
+ else:
+ return offres
+
+ def candidat_add(self, offre_id,):
+ url = settings.RECRUTEMENT_URLS[self.env] + "candidat_add/%s/" % offre_id
+ r = Resource(url)
+ params = self.request.POST
+ for k, up_file in self.request.FILES.items():
+ params[k] = up_file
+ opener = poster.streaminghttp.register_openers()
+ datagen, headers = poster.encode.multipart_encode(params)
+ request = urllib2.Request(url, datagen, headers)
+ resp = urllib2.urlopen(request)
+ if resp.code == STATUS_OK:
+ candidats = [c.object for c in serializers.deserialize("json", resp.read())]
+ if len(candidats) == 1:
+ return candidats[0]
+ return None
from captcha.fields import CaptchaField
-from auf.django.emploi import models as emploi
+from models import *
################################################################################
# OFFRE EMPLOI
################################################################################
-class CandidatPieceForm(inlineformset_factory(emploi.Candidat,
- emploi.CandidatPiece)):
- nom = forms.MultipleChoiceField(choices=emploi.TYPE_PIECE_CHOICES,
+class CandidatPieceForm(inlineformset_factory(Candidat,
+ CandidatPiece)):
+ nom = forms.MultipleChoiceField(choices=TYPE_PIECE_CHOICES,
widget=CheckboxSelectMultiple)
-class PostulerOffreEmploiForm(ModelForm):
- captcha = CaptchaField()
-
- def __init__(self, *args, **kwargs):
- self.offre_emploi = kwargs.pop('offre_emploi')
- super(PostulerOffreEmploiForm, self).__init__(*args, **kwargs)
- def save(self, *args, **kwargs):
- kwargs2 = kwargs.copy()
- kwargs2['commit'] = False
- postulation = super(PostulerOffreEmploiForm, self).save(*args, **kwargs2)
- if 'commit' not in kwargs or kwargs['commit']:
- postulation.save()
- return postulation
- class Meta:
- model = emploi.Candidat
- exclude = ('actif', 'offre_emploi',)
- fields = ('nom', 'prenom', 'genre', 'nationalite', 'situation_famille',
+POSTULER_FORM_EXCLUDES = ('actif', 'offre_emploi',)
+POSTULER_FORM_FIELDS = ('nom', 'prenom', 'genre', 'nationalite', 'situation_famille',
'nombre_dependant', 'niveau_diplome', 'employeur_actuel',
'poste_actuel', 'domaine_professionnel', 'telephone',
'email', 'adresse', 'ville', 'code_postal', 'etat_province',
- 'pays', 'captcha', )
+ 'pays', )
+
+class NoCaptchaPostulerOffreEmploiForm(ModelForm):
+ class Meta:
+ model = Candidat
+ exclude = POSTULER_FORM_EXCLUDES
+ fields = POSTULER_FORM_FIELDS
+
+class PostulerOffreEmploiForm(ModelForm):
+ captcha = CaptchaField()
+
+ class Meta:
+ model = Candidat
+ exclude = POSTULER_FORM_EXCLUDES
+ fields = POSTULER_FORM_FIELDS + ('captcha', )
from django.core.files.storage import FileSystemStorage
from tinymce import models as tinymce_models
from django.db import models
-import settings
-
import datamaster_modeles.models as ref
+import settings
### CONSTANTES ###
# HELP_TEXT
{{ offre_emploi }}. Ces champs seront \
automatiquement remplacés par les informations de \
chaque candidat."
-
+HELP_TEXT_EN_AFFICHAGE = "En cochant cette case, l'offre d'emploi sera affichée\
+ sur le site institutionnel dès qu'elle aura le statut \
+ 'En diffusion' et ce, jusqu'à la date limite."
STATUT_OFFRE_EMPLOI_CHOICES = (
('NOUV', 'Nouveau'),
- ('AFFI', 'Offre d\'emploi en affichage'),
+ ('AFFI', 'En diffusion'),
('EVAL', 'En évaluation des candidatures'),
('ENTR', 'En entrevue'),
('TERM', 'Terminé'),
class OffreEmploi(Metadata):
est_affiche = models.BooleanField(default=False,
- verbose_name=u"En affichage sur le site")
+ verbose_name=u"À afficher sur le site institutionnel",
+ help_text=HELP_TEXT_EN_AFFICHAGE)
statut = models.CharField(max_length=4, choices=STATUT_OFFRE_EMPLOI_CHOICES,
default='NOUV')
+ date_limite = models.DateField(verbose_name=u"Date limite",
+ help_text=HELP_TEXT_FORMAT_DATE,)
nom = models.CharField(max_length=255)
- resume = models.TextField(verbose_name=u"Résumé")
+ resume = models.TextField(verbose_name=u"Résumé", blank=True)
description = models.TextField()
poste = models.CharField(max_length=255)
poste_nom = models.CharField(max_length=255)
- date_limite = models.DateField(verbose_name=u"Date limite",
- help_text=HELP_TEXT_FORMAT_DATE,)
region = models.ForeignKey(ref.Region, db_column='region',
verbose_name=u"Région")
bureau = models.ForeignKey(ref.Bureau, db_column='bureau', )
adresse = models.CharField(max_length=255)
ville = models.CharField(max_length=255)
etat_province = models.CharField(max_length=255,
- verbose_name=u"État/Province")
+ verbose_name=u"État/Province", blank=True)
code_postal = models.CharField(max_length=255, blank=True)
pays = models.ForeignKey(ref.Pays, db_column='pays',
related_name='+')
# Upload de fichiers
-storage_prive = FileSystemStorage(settings.PRIVE_MEDIA_ROOT,
- base_url=settings.PRIVE_MEDIA_URL)
+storage_prive = FileSystemStorage(settings.OE_PRIVE_MEDIA_ROOT,
+ base_url=settings.OE_PRIVE_MEDIA_URL)
def candidat_piece_dispatch(instance, filename):
- path = u'%s/%s/%s_%s_%s/%s/%s' % ('emplois', instance.candidat.offre_emploi.id,
- instance.candidat.nom, instance.candidat.prenom, instance.candidat.id,
- instance.nom, filename)
+ path = u'%s/%s/%s' % ('emplois', instance.candidat.id, filename)
return path
class CandidatPiece(models.Model):
import os
from django.conf import settings
-# Absolute path to the directory that holds media.
-# Example: "/home/media/media.lawrence.com/"
-MEDIA_ROOT = getattr(settings, 'OE_MEDIA_ROOT',
- os.path.join(os.path.dirname(__file__), 'media'))
-PRIVE_MEDIA_ROOT = getattr(settings, 'OE_PRIV_MEDIA_ROOT',
- os.path.join(os.path.dirname(__file__), 'media_prive'))
+# default
+MEDIA_ROOT = getattr(settings, 'MEDIA_ROOT', None)
+PRIVE_MEDIA_ROOT = getattr(settings, 'PRIVE_MEDIA_ROOT', None)
+MEDIA_URL = getattr(settings, 'MEDIA_URL', None)
+PRIVE_MEDIA_URL = getattr(settings, 'PRIVE_MEDIA_URL', None)
-# URL that handles the media served from MEDIA_ROOT. Make sure to use a
-# trailing slash if there is a path component (optional in other cases).
-# Examples: "http://media.lawrence.com", "http://example.com/media/"
-MEDIA_URL = '/media/'
-PRIVE_MEDIA_URL = '/prive/'
+# custom
+OE_MEDIA_ROOT = getattr(settings, 'OE_MEDIA_ROOT', MEDIA_ROOT)
+OE_PRIVE_MEDIA_ROOT = getattr(settings, 'OE_PRIV_MEDIA_ROOT', PRIVE_MEDIA_ROOT)
+OE_MEDIA_URL = getattr(settings, 'OE_MEDIA_URL', MEDIA_URL)
+OE_PRIVE_MEDIA_URL = getattr(settings, 'OE_PRIVE_MEDIA_URL', PRIVE_MEDIA_URL)
+
+RECRUTEMENT_URLS = {'DEV': getattr(settings, 'RECRUTEMENT_URL', 'http://127.0.0.1:8000/api/'),
+ 'TEST':'http://test.ressources-humaines.auf.org/api/',
+ 'PROD':'http://ressources-humaines.auf.org/api/',}
--- /dev/null
+<table>
+ {% for f in piecesForm.management_form %}
+ {{ f }}
+ {% endfor %}
+ <tr>
+ <th></th>
+ {% for field in piecesForm.forms.0 %}
+ {% if not field.is_hidden %}
+ <th>{{ field.label }}</th>
+ {% endif %}
+ {% endfor %}
+ </tr>
+ {% for f in piecesForm.forms %}
+ <tr>
+ <td>
+ {{ f.errors }}
+ {% if f.initial.fichier %}
+ <a href="{{ f.initial.fichier.url }}" target="_blank">Télécharger</a>
+ {% endif %}
+ </td>
+ {% for field in f %}
+ {% if not field.is_hidden %}
+ <td>{{ field }}</td>
+ {% else %}
+ {{ field }}
+ {% endif %}
+ {% endfor %}
+ </tr>
+ {% endfor %}
+</table>
--- /dev/null
+{% extends "base.html" %}
+{% block Contenu%}
+
+<div id="content-main">
+ {% block object-tools %}{% endblock %}
+
+ <h1>Poster pour un appel d'offre d'emploi</h1>
+
+ <form action="" method="post" enctype="multipart/form-data">
+ <fieldset>
+ <h2>Informations personnelles</h2>
+ <table id="informations_personnelles">
+ <tbody>
+ <tr>
+ <td>{{ form.prenom.label }}</td>
+ <td>{{ form.prenom }}</td>
+ </tr>
+ <tr>
+ <td>{{ form.nom.label }}</td>
+ <td>{{ form.nom }}</td>
+ </tr>
+ <tr>
+ <td>{{ form.genre.label }}</td>
+ <td>{{ form.genre }}</td>
+ </tr>
+ <tr>
+ <td>{{ form.nationalite.label }}</td>
+ <td>{{ form.nationalite }}</td>
+ <tr>
+ <td>{{ form.situation_famille.label }}</td>
+ <td>{{ form.situation_famille }}</td>
+ </tr>
+ <tr>
+ <td>{{ form.nombre_dependant.label }}</td>
+ <td>{{ form.nombre_dependant }}<br />
+ <span class="info">{{ form.nombre_dependant.help_text }}</span>
+ </td>
+ </tr>
+ </tbody>
+ </table>
+ </fieldset>
+ <fieldset>
+ <h2>Coordonnées</h2>
+ <table id="coordonnees">
+ <tbody>
+ <tr>
+ <td>{{ form.telephone.label }}</td>
+ <td>{{ form.telephone }}</td>
+ </tr>
+ <tr>
+ <td>{{ form.email.label }}</td>
+ <td>{{ form.email }}</td>
+ </tr>
+ <tr>
+ <td>{{ form.adresse.label }}</td>
+ <td>{{ form.adresse }}</td>
+ </tr>
+ <tr>
+ <td>{{ form.ville.label }}</td>
+ <td>{{ form.ville }}</td>
+ </tr>
+ <tr>
+ <td>{{ form.etat_province.label }}</td>
+ <td>{{ form.etat_province }}</td>
+ </tr>
+ <tr>
+ <td>{{ form.code_postal.label }}</td>
+ <td>{{ form.code_postal }}</td>
+ </tr>
+ <tr>
+ <td>{{ form.pays.label }}</td>
+ <td>{{ form.pays }}</td>
+ </tr>
+ </tbody>
+ </table>
+ </fieldset>
+ <fieldset>
+ <h2>Informations professionnelles</h2>
+ <table id="informations_professionnelles">
+ <tbody>
+ <tr>
+ <td>{{ form.niveau_diplome.label }}</td>
+ <td>{{ form.niveau_diplome }}</td>
+ </tr>
+ <tr>
+ <td>{{ form.employeur_actuel.label }}</td>
+ <td>{{ form.employeur_actuel }}</td>
+ </tr>
+ <tr>
+ <td>{{ form.poste_actuel.label }}</td>
+ <td>{{ form.poste_actuel }}</td>
+ </tr>
+ <tr>
+ <td>{{ form.domaine_professionnel.label }}</td>
+ <td>{{ form.domaine_professionnel }}</td>
+ </tr>
+ </tbody>
+ </table>
+ </fieldset>
+ <fieldset>
+ <h2>Pièces jointes</h2>
+ <p class="info">CV, lettre de motivation...</p>
+ {% include "recrutement/pieces.html" %}
+ </fieldset>
+ <fieldset>
+ <h2>Vérification CAPTCHA</h2>
+ <p class="info">Entrez les caractères figurant dans l'image ci-dessous.</p>
+ <tr>
+ <td>
+ {{ form.captcha }}
+ {{ form.captcha.errors }}
+ </td>
+ </tr>
+ </fieldset>
+ <div class="submit-row">
+ <input type="submit" name="save" value="Enregistrer" />
+ </div>
+ </form>
+
+
+</div>
+
+{% endblock %}
+++ /dev/null
-<table>
- {% for f in piecesForm.management_form %}
- {{ f }}
- {% endfor %}
- <tr>
- <th></th>
- {% for field in piecesForm.forms.0 %}
- {% if not field.is_hidden %}
- <th>{{ field.label }}</th>
- {% endif %}
- {% endfor %}
- </tr>
- {% for f in piecesForm.forms %}
- <tr>
- <td>
- {{ f.errors }}
- {% if f.initial.fichier %}
- <a href="{{ f.initial.fichier.url }}" target="_blank">Télécharger</a>
- {% endif %}
- </td>
- {% for field in f %}
- {% if not field.is_hidden %}
- <td>{{ field }}</td>
- {% else %}
- {{ field }}
- {% endif %}
- {% endfor %}
- </tr>
- {% endfor %}
-</table>
+++ /dev/null
-{% extends 'base.html' %}
-{% load adminmedia %}
-
-{% block title %}RH{% endblock %}
-{% block titre %}Ressources humaines{% endblock %}
-{% block sous_titre %}Accueil{% endblock %}
-
-{% block main %}
-<div id="content-main">
- {% block object-tools %}{% endblock %}
-
-
-
-
- <div class="module">
- <h2>Poster pour un appel d'offre d'emploi</h2>
- </div>
-
- <form action="" method="post" enctype="multipart/form-data">
- <fieldset>
- <h2>Informations personnelles</h2>
- <table id="informations_personnelles">
- <tbody>
- <tr>
- <td>{{ form.prenom.label }}</td>
- <td>{{ form.prenom }}</td>
- </tr>
- <tr>
- <td>{{ form.nom.label }}</td>
- <td>{{ form.nom }}</td>
- </tr>
- <tr>
- <td>{{ form.genre.label }}</td>
- <td>{{ form.genre }}</td>
- </tr>
- <tr>
- <td>{{ form.nationalite.label }}</td>
- <td>{{ form.nationalite }}</td>
- <tr>
- <td>{{ form.situation_famille.label }}</td>
- <td>{{ form.situation_famille }}</td>
- </tr>
- <tr>
- <td>{{ form.nombre_dependant.label }}</td>
- <td>{{ form.nombre_dependant }}<br />
- <span class="info">{{ form.nombre_dependant.help_text }}
- </span>
- </td>
- </tr>
- </tbody>
- </table>
- </fieldset>
- <fieldset>
- <h2>Coordonnées</h2>
- <table id="coordonnees">
- <tbody>
- <tr>
- <td>{{ form.telephone.label }}</td>
- <td>{{ form.telephone }}</td>
- </tr>
- <tr>
- <td>{{ form.email.label }}</td>
- <td>{{ form.email }}</td>
- </tr>
- <tr>
- <td>{{ form.adresse.label }}</td>
- <td>{{ form.adresse }}</td>
- </tr>
- <tr>
- <td>{{ form.ville.label }}</td>
- <td>{{ form.ville }}</td>
- </tr>
- <tr>
- <td>{{ form.etat_province.label }}</td>
- <td>{{ form.etat_province }}</td>
- </tr>
- <tr>
- <td>{{ form.code_postal.label }}</td>
- <td>{{ form.code_postal }}</td>
- </tr>
- <tr>
- <td>{{ form.pays.label }}</td>
- <td>{{ form.pays }}</td>
- </tr>
- </tbody>
- </table>
- </fieldset>
- <fieldset>
- <h2>Informations professionnelles</h2>
- <table id="informations_professionnelles">
- <tbody>
- <tr>
- <td>{{ form.niveau_diplome.label }}</td>
- <td>{{ form.niveau_diplome }}</td>
- </tr>
- <tr>
- <td>{{ form.employeur_actuel.label }}</td>
- <td>{{ form.employeur_actuel }}</td>
- </tr>
- <tr>
- <td>{{ form.poste_actuel.label }}</td>
- <td>{{ form.poste_actuel }}</td>
- </tr>
- <tr>
- <td>{{ form.domaine_professionnel.label }}</td>
- <td>{{ form.domaine_professionnel }}</td>
- </tr>
- </tbody>
- </table>
- </fieldset>
- <fieldset>
- <h2>Pièces jointes</h2>
- <p class="info">CV, lettre de motivation...</p>
- {% include "recrutement/pieces.html" %}
- </fieldset>
- <fieldset>
- <h2>Vérification CAPTCHA</h2>
- <p class="info">Entrez les caractères figurant dans l'image ci-dessous.</p>
- <tr>
- <td>
- {{ form.captcha }}
- {{ form.captcha.errors }}
- </td>
- </tr>
- </fieldset>
- <div class="submit-row">
- <input type="submit" name="save" value="Enregistrer" />
- </div>
- </form>
-
-
-
-</div>
-
-{% endblock %}
import sys, os
name = 'auf.django.emploi'
-version = '0.1'
+version = '0.5'
setup(name=name,
version=version,
zip_safe=False,
install_requires=[
# -*- Extra requirements: -*-
+ 'restkit',
+ 'httplib2',
+ 'poster',
],
entry_points="""
# -*- Entry points: -*-