Merge branch 'master' of gitosis@git.auf:auf_savoirs_en_partage_django
authorAli Jetha <ali@U-AJ.(none)>
Mon, 4 Oct 2010 15:14:12 +0000 (11:14 -0400)
committerAli Jetha <ali@U-AJ.(none)>
Mon, 4 Oct 2010 15:14:12 +0000 (11:14 -0400)
auf_savoirs_en_partage/savoirs/admin.py
auf_savoirs_en_partage/savoirs/admin_views.py
auf_savoirs_en_partage/savoirs/forms.py
auf_savoirs_en_partage/savoirs/globals.py
auf_savoirs_en_partage/savoirs/lib/calendrier.py
auf_savoirs_en_partage/savoirs/lib/sep.py
auf_savoirs_en_partage/savoirs/models.py
auf_savoirs_en_partage/savoirs/views.py
auf_savoirs_en_partage/templates/savoirs/evenement.html
auf_savoirs_en_partage/templates/savoirs/index.html
buildout.cfg

index 7ee1ec0..3695b64 100644 (file)
@@ -15,7 +15,6 @@ from models import SourceActualite, Actualite, Discipline, Evenement, Record, Li
 from savoirs.globals import META
 
 admin.site.register(SourceActualite)
-admin.site.register(Evenement)
 
 class ListSetFilterSpec(RelatedFilterSpec):
     """
@@ -250,3 +249,26 @@ class ActualiteAdmin(admin.ModelAdmin):
         return HttpResponseRedirect("/admin/confirmation/%s/%s?ids=%s" % ('actualite', 'invisible', ",".join(selected)))
 
 admin.site.register(Actualite, ActualiteAdmin)
+
+
+class EvenementAdmin(admin.ModelAdmin):
+    list_filter = ('approuve',)
+    list_display = ('titre', 'debut', 'fin', 'lieu', 'approuve')
+    fields = ['titre',
+              'discipline',
+              'discipline_secondaire',
+              'mots_cles',
+              'type',
+              'fuseau',
+              'debut',
+              'fin',
+              'lieu',
+              'description',
+              'contact',
+              'url',
+              'approuve']
+
+admin.site.register(Evenement, EvenementAdmin)
+
+
+
index 497c049..be64dfa 100644 (file)
@@ -8,6 +8,7 @@ from django.shortcuts import render_to_response
 
 from datamaster_modeles.models import Thematique, Pays, Region
 from savoirs.models import Record, Discipline, Actualite, Serveur
+from savoirs.forms import PaysForm, RegionsForm, ThematiquesForm, DisciplinesForm, ConfirmationForm
 
 # Dashboard
 class RecordDashboard:
@@ -54,27 +55,6 @@ class RecordDashboard:
         records = self.mes_records()
         return [{'title':self.ref_apercu(r), 'url':self.change_url(r), 'external': False} for r in records]
 
-# Admin views pour les associations par lots
-
-class PaysForm(forms.Form):
-    values = [(p.id, p.nom) for p in Pays.objects.all()]
-    pays = forms.MultipleChoiceField(choices=values)
-
-class RegionsForm(forms.Form):
-    values = [(r.id, r.nom) for r in Region.objects.all()]
-    regions = forms.MultipleChoiceField(choices=values)
-
-class ThematiquesForm(forms.Form):
-    values = [(t.id, t.nom) for t in Thematique.objects.all()]
-    thematiques = forms.MultipleChoiceField(choices=values)
-
-class DisciplinesForm(forms.Form):
-    values = [(t.id, t.nom) for t in Discipline.objects.all()]
-    disciplines = forms.MultipleChoiceField(choices=values)
-
-class ConfirmationForm(forms.Form):
-    pass
-
 @login_required
 def assigner_pays(request):
     ids = request.GET.get("ids").split(",")
index 9f31c07..617555a 100644 (file)
@@ -1,6 +1,7 @@
 # -*- encoding: utf-8 -*-
 from django import forms
-from models import Evenement
+from datamaster_modeles.models import Thematique, Pays, Region
+from models import Evenement, Discipline
 
 class RechercheAvancee (forms.Form):
     creator = forms.CharField (max_length=60, required=False, \
@@ -17,4 +18,26 @@ class RechercheAvancee (forms.Form):
 class EvenementForm(forms.ModelForm):
     class Meta:
         model = Evenement
-        exclude = ('approuve', 'uid', 'actif')
+        exclude = ('approuve', 'uid')
+
+# Admin views pour les associations par lots
+
+class PaysForm(forms.Form):
+    values = [(p.id, p.nom) for p in Pays.objects.all()]
+    pays = forms.MultipleChoiceField(choices=values)
+
+class RegionsForm(forms.Form):
+    values = [(r.id, r.nom) for r in Region.objects.all()]
+    regions = forms.MultipleChoiceField(choices=values)
+
+class ThematiquesForm(forms.Form):
+    values = [(t.id, t.nom) for t in Thematique.objects.all()]
+    thematiques = forms.MultipleChoiceField(choices=values)
+
+class DisciplinesForm(forms.Form):
+    values = [(t.id, t.nom) for t in Discipline.objects.all()]
+    disciplines = forms.MultipleChoiceField(choices=values)
+
+class ConfirmationForm(forms.Form):
+    pass
+
index 9795fc6..fe17c71 100644 (file)
@@ -11,7 +11,7 @@ configuration = {
     'accueil_evenement': 10,
     'engin_recherche': 'sep',
     'google_xml': "http://www.savoirsenpartage.auf.org/recherche.xml?%s",
-    'calendrier_publique': 'http://cal.ro.auf.org/caldav.php/davin/test/',
+    'calendrier_publique': 'https://sep-caldav.auf.org/caldav.php/sep/home',
 }
 
 #####
index 7724606..9965637 100644 (file)
@@ -19,21 +19,15 @@ def evenements():
 
     return rc
 
-
-
 def evenement_info(uid):
     client = caldav.DAVClient(CALENDRIER_URL)
     cal = caldav.Calendar(client, url = CALENDRIER_URL)
     return cal.event(uid)
 
-def evenement_publie(event):
-    client = caldav.DAVClient(CALENDRIER_URL)
-    cal = caldav.Calendar(client, url = CALENDRIER_URL)
-    e = caldav.Event(client, parent = cal, data = event.serialize()).save()
 
 def combine(when, tz):
     r = datetime.datetime(when.year, when.month, when.day, 
-                          when.hour, when.minute, tzinfo = pytz.timezone(tz))
+                          when.hour, when.minute, tzinfo = pytz.timezone(unicode(tz)))
     #r = r.replace(tzinfo = pytz.timezone("UTC"))
     t = r.utctimetuple()
     r = datetime.datetime(t[0],t[1],t[2],t[3],t[4],t[5], 
index 56b5cc3..7a6aae3 100644 (file)
@@ -152,11 +152,11 @@ class SEP:
 
         q = "SELECT r.id, (%s) AS score FROM savoirs_record AS r \
              LEFT JOIN savoirs_record_listsets AS rl ON r.id = rl.record_id \
-             JOIN savoirs_listset AS l ON rl.listset_id = l.spec \
+             LEFT JOIN savoirs_listset AS l ON rl.listset_id = l.spec \
              WHERE (%s) AND r.validated = 1 AND l.validated = 1 \
              GROUP BY r.id \
              HAVING score > 0 ORDER BY score DESC" % (m, m)
-
+        print q
         from django.db import connection, transaction
         cursor = connection.cursor()
         cursor.execute(q)
index d042724..828b6bf 100644 (file)
@@ -1,13 +1,15 @@
 # -*- encoding: utf-8 -*-
+import simplejson, uuid, datetime, caldav, vobject, uuid
 from django.contrib.auth.models import User
 from django.db import models
-from django.db.models.signals import post_save
-import simplejson
-import uuid, datetime
+from django.db.models.signals import pre_delete
 from timezones.fields import TimeZoneField
 from auf_savoirs_en_partage.backend_config import RESOURCES
 from savoirs.globals import META
+from settings import CALENDRIER_URL
 from datamaster_modeles.models import Thematique, Pays, Region
+from lib.calendrier import combine
+from caldav.lib import error
 
 class Discipline(models.Model):
     id = models.IntegerField(primary_key=True, db_column='id_discipline')
@@ -44,14 +46,8 @@ class Actualite(models.Model):
         db_table = u'actualite'
         ordering = ["-date",]
 
-
-class ActiveManager(models.Manager):
-    def get_query_set(self):
-        return super(ActiveManager, self).get_query_set().filter(actif=True)
-
 class Evenement(models.Model):
-    actif = models.BooleanField(default = True)
-    uid = models.CharField(max_length = 255, default = uuid.uuid1)
+    uid = models.CharField(max_length = 255, default = None)
     approuve = models.BooleanField(default = False)
     titre = models.CharField(max_length=255)
     discipline = models.ForeignKey('Discipline', related_name = "discipline", 
@@ -78,11 +74,99 @@ class Evenement(models.Model):
     contact = models.TextField(blank = True, null = True)
     url = models.CharField(max_length=255, blank = True, null = True)
 
-    objects = ActiveManager()
-
     def __unicode__(self,):
         return "[%s] %s" % (self.uid, self.titre)
 
+    def save(self, *args, **kwargs):
+        """Sauvegarde l'objet dans django et le synchronise avec caldav s'il a été
+        approuvé"""
+        self.update_vevent()
+        super(Evenement, self).save(*args, **kwargs)
+
+    # methodes de commnunications avec CALDAV
+    def as_ical(self,):
+        """Retourne l'evenement django sous forme d'objet icalendar"""
+        cal = vobject.iCalendar()
+        cal.add('vevent')
+
+        # fournit son propre uid
+        if self.uid is None:
+            self.uid = str(uuid.uuid1())
+
+        cal.vevent.add('uid').value = self.uid
+        
+        cal.vevent.add('summary').value = self.titre
+        
+        if self.mots_cles is None:
+            kw = []
+        else:
+            kw = self.mots_cles.split(",")
+
+        try:
+            kw.append(self.discipline.nom)
+            kw.append(self.discipline_secondaire.nom)
+            kw.append(self.type)
+        except: pass
+
+        kw = [x.strip() for x in kw if len(x.strip()) > 0]
+        for k in kw:
+            cal.vevent.add('x-auf-keywords').value = k
+
+        description = self.description
+        if len(kw) > 0:
+            if len(self.description) > 0:
+                description += "\n"
+            description += u"Mots-clés: " + ", ".join(kw)
+
+        cal.vevent.add('dtstart').value = combine(self.debut, self.fuseau)
+        cal.vevent.add('dtend').value = combine(self.fin, self.fuseau)
+        cal.vevent.add('created').value = combine(datetime.datetime.now(), "UTC")
+        cal.vevent.add('dtstamp').value = combine(datetime.datetime.now(), "UTC")
+        if len(self.description) > 0:
+            cal.vevent.add('description').value = description
+        if len(self.contact) > 0:
+            cal.vevent.add('contact').value = self.contact
+        if len(self.url) > 0:
+            cal.vevent.add('url').value = self.url
+        if len(self.lieu) > 0:
+            cal.vevent.add('location').value = self.lieu
+        return cal
+
+    def update_vevent(self,):
+        """Essaie de créer l'évènement sur le serveur ical.
+        En cas de succès, l'évènement local devient donc inactif et approuvé"""
+        try:
+            if self.approuve:
+                event = self.as_ical()
+                client = caldav.DAVClient(CALENDRIER_URL)
+                cal = caldav.Calendar(client, url = CALENDRIER_URL)
+                e = caldav.Event(client, parent = cal, data = event.serialize(), id=self.uid)
+                e.save()
+        except:
+            self.approuve = False
+
+    def delete_vevent(self,):
+        """Supprime l'evenement sur le serveur caldav"""
+        try:
+            if self.approuve:
+                event = self.as_ical()
+                client = caldav.DAVClient(CALENDRIER_URL)
+                cal = caldav.Calendar(client, url = CALENDRIER_URL)
+                e = cal.event(self.uid)
+                e.delete()
+        except error.NotFoundError:
+            pass
+
+
+# Surcharge du comportement de suppression
+# La méthode de connexion par signals est préférable à surcharger la méthode delete()
+# car dans le cas de la suppression par lots, cell-ci n'est pas invoquée
+def delete_vevent(sender, instance, *args, **kwargs):
+    instance.delete_vevent()
+
+pre_delete.connect(delete_vevent, sender = Evenement) 
+
+
 class ListSet(models.Model):
     spec = models.CharField(primary_key = True, max_length = 255)
     name = models.CharField(max_length = 255)
@@ -139,40 +223,11 @@ class Record(models.Model):
            self.pays.count() > 0 and \
            self.regions.count() > 0
 
-
     def __unicode__(self):
         return "[%s] %s" % (self.server, self.title)
 
-# Ces fonctions sont utilisées pour travailler directement sur les données JSON enregistrées tel quel
-# sur la base de données. Lorsque le modèle est initialisé, les fields sont décodés, et lorsque l'objet
-# est sauvegardé, on s'assure de remettre les données encodées en  JSON.
-# TODO : a terme, les données ne seront plus stockées au format JSON dans la BD et ces fonctions seront
-# donc obsolètes.
-#
-#    def save(self, *args, **kwargs):
-#        
-#        for field_name in [f for f in self._meta.get_all_field_names() if f in META.keys()]:
-#            v = getattr (self, field_name, None)
-#            setattr(self, field_name, simplejson.dumps(v))
-#
-#        super(Record, self).save(*args, **kwargs)
-#
-#def decode_json(instance, **kwargs):
-#  for field_name in [f for f in instance._meta.get_all_field_names() if f in META.keys()]:
-#      json = getattr(instance, field_name)
-#      data = "-"
-#      v = getattr (instance, field_name, None)
-#      if v is not None:
-#          data = simplejson.loads(v)
-#      if not isinstance(data, basestring):
-#        decoded_value =  u",".join(data)
-#      else:
-#        decoded_value = data
-#      setattr(instance, field_name, decoded_value)
-#
-#models.signals.post_init.connect(decode_json, Record)
-
 class Serveur(models.Model):
+    """Identification d'un serveur d'ou proviennent les références"""
     nom = models.CharField(primary_key = True, max_length = 255)
 
     def __unicode__(self,):
index 9a52875..5caecf1 100644 (file)
@@ -9,7 +9,7 @@ from django.core.urlresolvers import reverse
 from django import forms
 from lib.recherche import cherche, google_search
 from lib import sep
-from lib.calendrier import evenements, evenement_info, evenement_publie, combine
+from lib.calendrier import evenements, evenement_info, combine
 from savoirs.globals import configuration
 import backend_config
 from forms import *
@@ -141,45 +141,7 @@ def evenement_moderation(request):
 @login_required
 def evenement_accepter(request, pk):
     e = Evenement.objects.get(pk = pk)
-
-    cal = vobject.iCalendar()
-    cal.add('vevent')
-    cal.vevent.add('summary').value = e.titre
-    
-    kw = e.mots_cles.split(",")
-    try:
-        kw.append(e.discipline.nom)
-        kw.append(e.discipline_secondaire.nom)
-        kw.append(e.type)
-    except: pass
-
-    kw = [x.strip() for x in kw if len(x.strip()) > 0]
-    for k in kw:
-        cal.vevent.add('x-auf-keywords').value = k
-
-    if len(kw) > 0:
-        if len(e.description) > 0:
-            e.description += "\n"
-        e.description += u"Mots-cles: " + ", ".join(kw)
-
-    cal.vevent.add('dtstart').value = combine(e.debut, e.fuseau)
-    cal.vevent.add('dtend').value = combine(e.fin, e.fuseau)
-    cal.vevent.add('created').value = combine(datetime.datetime.now(), "UTC")
-    cal.vevent.add('dtstamp').value = combine(datetime.datetime.now(), "UTC")
-    if len(e.description) > 0:
-        cal.vevent.add('description').value = e.description
-    if len(e.contact) > 0:
-        cal.vevent.add('contact').value = e.contact
-    if len(e.url) > 0:
-        cal.vevent.add('url').value = e.url
-    if len(e.lieu) > 0:
-        cal.vevent.add('location').value = e.lieu
-
-    evenement_publie(cal)
-
-    e.actif = False
     e.save()
-
     return HttpResponseRedirect(reverse('savoirs.views.evenement_moderation'))
 
 @login_required
index c2a89e2..3efc953 100644 (file)
@@ -14,7 +14,7 @@
       <td>{{ event.dtend.value|date:"Y-m-d H:i" }} (UTC)</td>
     </tr>
     <tr>
-      <th>Déscription</th>
+      <th>Description</th>
       <td>{{ event.description.value|linebreaksbr }}</td>
     </tr>
     <tr>
index 3f4341d..5d76f4b 100644 (file)
@@ -49,9 +49,6 @@
         <ul class="sous-menu">
             <li><a href="{% url savoirs.views.evenement_ajout %}">Soumettre un événement</a></li>
             <li><a href="{{ caldav_url }}">S'abonner</a></li>
-            {% if user.is_authenticated %}
-            <li><a href="{% url savoirs.views.evenement_moderation %}">Modération</a></li>
-            {% endif %}
         </ul>
         <ul class="liste-de-l-accueil">
         {% for event in events %}
index 384ebf1..9897e9d 100644 (file)
@@ -1,4 +1,5 @@
 [buildout]
+newest = false
 parts = django articles harvest
 find-links = http://pypi.auf.org/caldav/
     http://pypi.auf.org/auf_references_client/
@@ -14,7 +15,7 @@ wsgi = true
 settings = production
 extra-paths = auf_savoirs_en_partage
 eggs = auf_references_client
-    caldav==0.1.4.2-auf
+    caldav==0.1.4.3-auf
     chardet
     pytz
     django-timezones