TP : Agenda - Models

date:2012-05-01 21:34
tags:django, python
category:Django
author:Rémy Hubscher

Énoncé

Nous souhaitons réaliser un agenda qui nous permettra :

  • De gérer plusieurs agenda
  • D’intégrer des événements dans l’agenda
  • D’ajouter, modifier, supprimer, déplacer un événement

L’IHM

En fait vous allez voir que ce qu’il y a de plus dur dans un agenda web, c’est l’IHM.

Ce n’est pas le but de ce TP, mais à quoi bon avoir un code basé sur Django si au niveau du frontend, la qualité ne suit pas ?

Comme IHM, je vous propose d’utiliser FullCalendar.

Création de l’app

$ python manage.py startapp schedule

C’est une app réutilisable.

On ajoute schedule dans le INSTALLED_APP.

Gérer les migrations avec South

Cette fois, comme nous allons sûrement améliorer notre application par la suite en ajoutant un auteur, une description, un lieu, etc. Nous allons donc utiliser South

$ pip install South

On ajoute south dans le INSTALLED_APP et on lance le syncdb

$ python manage.py syncdb

Les modèles

Nous avons dit, plusieurs calendriers/agenda, il faut donc stocker les agendas.

models.py

# -*- coding: utf-8 -*-
from django.db import models
from django.utils.translation import ugettext_lazy as _

class Calendar(models.Model):
    name = models.CharField(_('name'), max_length=50)
    slug = models.SlugField(_('slug'), unique=True)

    def __unicode__(self):
        return u'%s' % self.name

    class Meta:
        verbose_name = _('calendar')
        ordering = ['name']

Ensuite nous souhaitons créer des événements liés à un calendrier :

class Event(models.Model):
    title = models.CharField(_('title'), max_length=100)
    start = models.DateTimeField(_('start'))
    end = models.DateTimeField(_('start'))

    calendar = models.ForeignKey(Calendar)

    def __unicode__(self):
        return u'%s' % self.title

    class Meta:
        verbose_name = _('event')
        ordering = ['start', 'end']

Notre première migration

On ne fait pas de syncdb, mais on va créer notre migration initiale

$ python manage.py schemamigration --initial schedule
Creating migrations directory at '/home/rhubscher/hg/django-story/demos/tuto_django/schedule/migrations'...
Creating __init__.py in '/home/rhubscher/hg/django-story/demos/tuto_django/schedule/migrations'...
 + Added model schedule.Calendar
 + Added model schedule.Event
Created 0001_initial.py. You can now apply this migration with: ./manage.py migrate schedule

Appliquer une migration

Pour appliquer notre migration, nous pouvons faire

$ python manage.py migrate schedule

Le premier syncdb

Lors de la création d’une base neuve, il sera possible de faire

$ python manage.py syncdb
$ python manage.py migrate

ou en une fois

$ python manage.py syncdb --migrate

Ainsi les app gérées avec South, feront le migrate et les autres le syncdb.

Migration suivante

Si nous souhaitons avoir la possibilité d’annuler un événement, nous pouvons modifier notre modèle comme suit :

class Event(models.Model):
    title = models.CharField(_('title'), max_length=100)
    start = models.DateTimeField(_('start'))
    end = models.DateTimeField(_('end'))
    is_cancelled = models.BooleanField(_('Cancelled?'), default=False, blank=True)

    calendar = models.ForeignKey(Calendar)

    def __unicode__(self):
        return u'%s' % self.title

    class Meta:
        verbose_name = _('event')
        ordering = ['start', 'end']

Et nous voyons ici tout l’intérêt de South.

Précédement, il nous aurait fallu supprimer la table event pour la recréer. Maintenant, nous allons simplement faire une nouvelle migration

$ python manage.py schemamigration --auto schedule
 + Added field is_cancelled on schedule.Event
Created 0002_auto__add_field_event_is_cancelled.py. You can now apply this migration with: ./manage.py migrate schedule

Puis on applique la migration

$ python manage.py migrate schedule

L’administration

Activation

On va ensuite activer l’administration.

admin.py

Maintenant nous pouvons créer des calendriers et y lier des événements.

../_images/admin1.png ../_images/admin-events.png

Configuration

L’administration Django peut être configurée au petit oignons.

Par exemple, nous souhaitons que le slug se remplisse automatiquement à partir du nom de notre calendrier :

class CalendarAdmin(admin.ModelAdmin):
    prepopulated_fields = {"slug": ("name",)}

admin.site.register(Calendar, CalendarAdmin)

Nous souhaitons aussi pouvoir rechercher dans les événements, afficher la date de début et de fin dans la liste et pouvoir naviguer par date dans les événements :

class EventAdmin(admin.ModelAdmin):
    list_display = ('title', 'start', 'end')
    search_fields = ['title']
    date_hierarchy = 'start'

admin.site.register(Event, EventAdmin)

Bonus

Vous pouvez améliorer l’interface avec django-grappelli.

Installer grappelli

$ pip install django-grappelli

Configurer le settings.py en ajoutant grappelli juste avant django.contrib.admin dans le INSTALLED_APP :

INSTALLED_APPS = (
    ...
    'grappelli',
    'django.contrib.admin',
    ...
)

Ajouter les urls vers les views de grappelli et servez les fichiers static :

urlpatterns = patterns('',
        ...
    url(r'^grappelli/', include('grappelli.urls')),
)

from django.contrib.staticfiles.urls import staticfiles_urlpatterns
urlpatterns += staticfiles_urlpatterns()

Juste après la définition de STATIC_URL dans le fichier settings.py ajoutez :

ADMIN_MEDIA_PREFIX = STATIC_URL + "grappelli/"

Et voici le résultat :

../_images/admin-events-grappelli.png

Conclusion

Nous avons deux modèles, nous avons mis en place South pour nous permettre de continuer à améliorer simplement nos modèles, nous avons configurer l’administration et installer django-grappelli.

Nous sommes prêt pour mettre en place les templates.