from savoirs.globals import META
admin.site.register(SourceActualite)
-admin.site.register(Evenement)
class ListSetFilterSpec(RelatedFilterSpec):
"""
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)
+
+
+
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:
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(",")
# -*- 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, \
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
+
'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',
}
#####
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],
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)
# -*- 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')
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",
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)
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,):
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 *
@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
<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>
<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 %}
[buildout]
+newest = false
parts = django articles harvest
find-links = http://pypi.auf.org/caldav/
http://pypi.auf.org/auf_references_client/
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