refactoring pour couplage fort model form, abstraction utilisation JSON
authorOlivier Larchevêque <olivier.larcheveque@auf.org>
Mon, 15 Aug 2011 21:46:58 +0000 (17:46 -0400)
committerOlivier Larchevêque <olivier.larcheveque@auf.org>
Mon, 15 Aug 2011 21:46:58 +0000 (17:46 -0400)
project/recrutement/api.py
project/urls.py
src/auf.django.emploi/auf/django/emploi/api.py
src/auf.django.emploi/auf/django/emploi/forms.py
src/auf.django.emploi/auf/django/emploi/settings.py

index 88001dd..e6c1bf0 100644 (file)
@@ -1,4 +1,5 @@
 # -*- encoding: utf-8 -*
+from django.core import serializers
 from datetime import date
 from django.http import HttpResponse
 from django.template import RequestContext, Template
@@ -20,7 +21,7 @@ STATUS_ERROR_NOT_FOUND = 404
 STATUS_ERROR_PERMISSIONS = 403
 STATUS_ERROR_BADMETHOD = 405
 
-def api(request, method, offre_id=None):
+def api(request, method, *args, **kwargs):
     # TODO: Sécurité : 
     #       L'échange d'information doit être possible qu'avec les HOST désirés.
 
@@ -28,13 +29,14 @@ def api(request, method, offre_id=None):
     #    return api_return(STATUS_ERROR_BADMETHOD)
 
     api = API(request)
-    if hasattr(api, 'api_%s' % method):
-        if offre_id is None:
-            return getattr(api, 'api_%s' % method)()
-        else:
-            return api.api_candidat_add(offre_id)
+    if not hasattr(api, 'api_%s' % method):
+        return api_return(STATUS_ERROR)
+    if kwargs.has_key('offre_id'):
+        offre_id = kwargs['offre_id']
+        return api.api_candidat_add(offre_id)
+    else:
+        return getattr(api, 'api_%s' % method)()
     
-    return api_return(STATUS_ERROR)
 
 def api_return(status, text='', json=False):
     content_type = 'text/html'
@@ -69,108 +71,44 @@ class API:
         offre = emploi.OffreEmploi.objects.get(id=offre_id)
 
         if self.request.method == "POST":
-            try:
-                candidat = emploi.Candidat()
-                candidat.offre_emploi = offre
-                candidat.nom = self.request.POST['nom']
-                candidat.prenom = self.request.POST['prenom']
-                candidat.genre = self.request.POST['genre']
-                candidat.nationalite = ref.Pays.objects.get\
-                                        (id=self.request.POST['nationalite'])
-                candidat.situation_famille = self.request.POST['situation_famille']
-                candidat.nombre_dependant = self.request.POST['nombre_dependant']
-                candidat.niveau_diplome = self.request.POST['niveau_diplome']
-                candidat.employeur_actuel = self.request.POST['employeur_actuel']
-                candidat.poste_actuel = self.request.POST['poste_actuel']
-                candidat.domaine_professionnel = self.request.\
-                                                    POST['domaine_professionnel']
-                candidat.telephone = self.request.POST['telephone']
-                candidat.email = self.request.POST['email']
-                candidat.adresse = self.request.POST['adresse']
-                candidat.ville = self.request.POST['ville']
-                candidat.etat_province = self.request.POST['etat_province']
-                candidat.code_postal = self.request.POST['code_postal']
-                candidat.pays = ref.Pays.objects.get(id=self.request.POST['pays'])
-                candidat.save()
-
-                for i in range(0, int(self.request.POST['candidat_piece-TOTAL_FORMS'])-1):
-                    if self.request.POST['candidat_piece-' + str(i) + '-nom'] is not None:
-                        piece = emploi.CandidatPiece()
-                        piece.candidat = candidat
-                        piece.nom = self.request.POST['candidat_piece-' + str(i) + '-nom']
-                        piece.path = self.request.META['QUERY_STRING']
-                        piece.save()
-
-                evaluateurs = candidat.offre_emploi.evaluateurs.all()
-                for evaluateur in evaluateurs:                
-                    candidat_evaluation = CandidatEvaluation()
-                    candidat_evaluation.candidat = candidat
-                    candidat_evaluation.evaluateur = evaluateur
-                    candidat_evaluation.save()
-
-                try:
-                    courriel_template = CourrielTemplate.objects.get(id=1)
-                    send_templated_email(candidat, courriel_template)
-                except:
-                    return api_return(STATUS_OK, simplejson.dumps(
-                                        {'candidat_id': candidat.id}), json=True)               
-            except:
-                return api_return(STATUS_ERROR)
-            return api_return(STATUS_OK, simplejson.dumps(
-                                {'candidat_id': candidat.id}), json=True)  
-        return api_return(STATUS_ERROR_BADMETHOD)
+            candidat = emploi.Candidat()
+            candidat.offre_emploi = offre
+            form = emploiForms.NoCaptchaPostulerOffreEmploiForm(self.request.POST, instance=candidat)
+            if form.is_valid():
+                candidat = form.save()
+                data = serializers.serialize('json', [candidat,])
+                return api_return(STATUS_OK, data)  
+            else:
+                return api_return(STATUS_ERROR, form.errors)
+
+            #    evaluateurs = candidat.offre_emploi.evaluateurs.all()
+            #    for evaluateur in evaluateurs:                
+            #        candidat_evaluation = CandidatEvaluation()
+            #        candidat_evaluation.candidat = candidat
+            #        candidat_evaluation.evaluateur = evaluateur
+            #        candidat_evaluation.save()
+
+            #    try:
+            #        courriel_template = CourrielTemplate.objects.get(id=1)
+            #        send_templated_email(candidat, courriel_template)
+            #    except:
+            #        return api_return(STATUS_OK, simplejson.dumps(
+            #                            {'candidat_id': candidat.id}), json=True)               
+            #except:
+            #    return api_return(STATUS_ERROR)
         
 
     def api_offre_emploi_liste(self):
-        offres_emploi = []
-        for offre in emploi.OffreEmploi.objects.all():
-            if offre.est_affiche is True and \
-                offre.statut == "AFFI" and \
-                offre.date_limite >= date.today():
-                offres_emploi.append(offre)
-        if offres_emploi:
-            return api_return(STATUS_OK, simplejson.dumps(
-                        [{"id": "%s" % offre.id, 
-                        "est_affiche": "%s" % offre.est_affiche,
-                        "statut": "%s" % offre.statut,
-                        "nom": "%s" % offre.nom, 
-                        "resume": "%s" % offre.resume,
-                        "description": "%s" % offre.description,
-                        "poste_nom": "%s" % offre.poste_nom,
-                        "region": "%s" % offre.region.id,
-                        "bureau": "%s" % offre.bureau.id,
-                        "date_limite": "%s" % offre.date_limite,
-                        "duree_affectation": "%s" % offre.duree_affectation,
-                        "renumeration": "%s" % offre.renumeration,
-                        "debut_affectation": "%s" % offre.debut_affectation,
-                        "lieu_affectation": "%s" % offre.lieu_affectation.id} 
-                                for offre in offres_emploi]), json=True)
-        return api_return(STATUS_OK)
+        offres_visibles =  emploi.OffreEmploi.objects.filter(est_affiche=True, statut="AFFI", date_limite__gte=date.today())
+        data = serializers.serialize('json', offres_visibles)
+        return api_return(STATUS_OK, data);
         
     def api_offre_emploi(self):
         try:
-            offre = emploi.OffreEmploi.objects.get(id=self.request.GET.get('id'))
+            id = self.request.GET.get('id')
+            offre = emploi.OffreEmploi.objects.get(id=id, statut="AFFI", date_limite__gte=date.today())
         except emploi.OffreEmploi.DoesNotExist:
             return api_return(STATUS_ERROR, "ID d'offre d'emploi invalide")
     
-        if offre.est_affiche is True and \
-            offre.statut == "AFFI" and \
-            offre.date_limite >= date.today():
-            return api_return(STATUS_OK, simplejson.dumps(
-                {"id": "%s" % offre.id,
-                "est_affiche": "%s" % offre.est_affiche,
-                "statut": "%s" % offre.statut,
-                "nom": "%s" % offre.nom, 
-                "resume": "%s" % offre.resume,
-                "description": "%s" % offre.description,
-                "poste_nom": "%s" % offre.poste_nom,
-                "region": "%s" % offre.region.id,
-                "bureau": "%s" % offre.bureau.id,
-                "date_limite": "%s" % offre.date_limite,
-                "duree_affectation": "%s" % offre.duree_affectation,
-                "renumeration": "%s" % offre.renumeration,
-                "debut_affectation": "%s" % offre.debut_affectation,
-                "lieu_affectation": "%s" % offre.lieu_affectation.id}), 
-                                                                    json=True)
-        return api_return(STATUS_OK)
-
+        data = serializers.serialize('json', [offre])
+        return api_return(STATUS_OK, data)
index 8a539f9..5e9f2f6 100644 (file)
@@ -14,7 +14,7 @@ urlpatterns = patterns(
     url(r'^$', 'project.views.accueil', name='accueil'),
 
     (r'^admin/', include(admin.site.urls)),
-    url(r'^api/(?P<method>[a-z_-]+)/(?P<offre_id>\d+)$', 'recrutement.api.api', 
+    url(r'^api/(?P<method>[a-z_-]+)/(?P<offre_id>\d+)/$', 'recrutement.api.api', 
             name='recrutement_api'),
     url(r'^api/(?P<method>[a-z_-]+)/$', 'recrutement.api.api', 
             name='recrutement_api'),
index 9e9d815..80cf08f 100644 (file)
 # -*- 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 restkit import request as req
-from restkit import Resource
-from httplib2 import Http
-from urllib import urlencode
+from restkit import request, Resource
 import datamaster_modeles.models as ref
-from poster.encode import MultipartParam
-from poster.encode import multipart_encode
+import poster
 import urllib2
 import settings
 
 
-STATUS_OK = '200 OK'
+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, env):
-
-        if hasattr(settings, "RECRUTEMENT_URL"):
-            url = getattr(settings, "RECRUTEMENT_URL")[env] + "offre_emploi_liste/"
-        else:
-            raise ImportError, "Could not import settings RECRUTEMENT_PATH"
+    def offre_emploi_liste(self,):
+        url = settings.RECRUTEMENT_URLS[self.env] + "offre_emploi_liste/"
         r = req(url)
-        liste_json = r.body_string()
-        try:
-            liste_offres = simplejson.loads(liste_json)
-        except:
-            return []
-        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, env):
-        if hasattr(settings, "RECRUTEMENT_URL"):
-            url = getattr(settings, "RECRUTEMENT_URL")[env] + "offre_emploi/?id=%s"
-        else:
-            raise ImportError, "Could not import settings RECRUTEMENT_PATH"
+        url = settings.RECRUTEMENT_URLS[self.env] + "offre_emploi/?id=%s"
         r = req(url % offre_id)
         offre_json = r.body_string()
-
-        try:
-            offre_dict = simplejson.loads(offre_json)
-        except:
-            return []
-        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, env):
-        if hasattr(settings, "RECRUTEMENT_URL"):
-            url = getattr(settings, "RECRUTEMENT_URL")[env] + "candidat_add/%s"
+        data = r.body_string()
+        offres = [o.object for o in serializers.deserialize("json", data)]
+        if len(offres) == 0:
+            return offres[0]
         else:
-            raise ImportError, "Could not import settings RECRUTEMENT_PATH"
-        r = Resource(url % offre_id)
-        mp = MultipartParam.from_file('cv', self.request.POST.get('candidat_piece-0-nom'))
-        datagen, headers = multipart_encode([image_param])
-        resp = r.post(payload=self.request.FILES, params_dict=self.request.POST)
-        if resp.status == STATUS_OK:
-            candidat_id = simplejson.loads(resp.body_string())['candidat_id']
-            return candidat_id
+            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
+        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
         
index 7a4a9e3..2801738 100644 (file)
@@ -24,27 +24,23 @@ class CandidatPieceForm(inlineformset_factory(Candidat,
         super(CandidatPieceForm, self).save(*args, **kwargs)
 
 
-class PostulerOffreEmploiForm(ModelForm):
-    captcha = CaptchaField()
-    action = "http://127.0.0.1:8000/api/candidat_add/"
+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', )
 
-    def __init__(self, *args, **kwargs):
-        self.offre_emploi = kwargs.pop('offre_id')
-        super(PostulerOffreEmploiForm, self).__init__(*args, **kwargs)
+class NoCaptchaPostulerOffreEmploiForm(ModelForm):
+    class Meta:
+        model = Candidat
+        exclude = POSTULER_FORM_EXCLUDES
+        fields =  POSTULER_FORM_FIELDS
 
-    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 PostulerOffreEmploiForm(ModelForm):
+    captcha = CaptchaField()
 
     class Meta:
         model = Candidat   
-        exclude = ('actif', 'offre_emploi',)
-        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', )
+        exclude = POSTULER_FORM_EXCLUDES
+        fields =  POSTULER_FORM_FIELDS + ('captcha', )
index 0772d21..1786be2 100644 (file)
@@ -16,6 +16,6 @@ PRIVE_MEDIA_ROOT = getattr(settings, 'OE_PRIV_MEDIA_ROOT',
 MEDIA_URL = '/media/'
 PRIVE_MEDIA_URL = '/prive/'
 
-RECRUTEMENT_URL = {'DEV':'http://127.0.0.1:8000/api/',
+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/',}