Du modèle Python vers la base de données
Support primitif pour générer un modèle à partir d'une base existante (rétro-ingénierie pour démarrer un projet).
from django.db import models
class Adherent(models.Model): nom = models.CharField("nom", maxlength=50) prenom = models.CharField("prénom", maxlength=50) naissance = models.DateField("date de naissance") email = models.EmailField("e-mail", null=False) adhesion = models.DateField("date d'adhésion", auto_now=True, editable=False) echeance = models.DateField("date d'échéance", null=False)
Créer le modèle en base :
./manage.py syncdb
Code DDL exécuté pour SQLite3 :
BEGIN; CREATE TABLE "adherent" ( "id" integer NOT NULL PRIMARY KEY, "nom" varchar(50) NOT NULL, "prenom" varchar(50) NOT NULL, "naissance" date NOT NULL, "email" varchar(75) NOT NULL, "adhesion" date NOT NULL, "echeance" date NOT NULL ); COMMIT;
./manage.py runserver
Manipuler les données, avec la console Python :
$ ./manage.py shell >>> from si.models import Adherent >>> Adherent.objects.all() [] >>> from datetime import date >>> om = Adherent(nom='Mengué', prenom='Olivier', ... naissance=date(1974, 1, 1), ... adhesion=date(2000, 9, 5), ... echeance=date(2007, 9, 4)) >>> om.save() >>> Adherent.objects.all() [<Adherent: Mengué, Olivier>]
from django.db import models from datetime import date
class Adherent(models.Model): nom = models.CharField("nom", maxlength=50) prenom = models.CharField("prénom", maxlength=50) # ...
def __str__(self): return '%s, %s' % (self.nom, self.prenom)
class Meta: db_table = 'adherent' verbose_name = 'Adhérent' verbose_name_plural = 'Adhérents'
def cotisation_a_jour(self): return self.echeance > date.today()
L'API de requêtage utilise la reflexivité de Python
>>> Adherent.objects.all() [<Adherent: Mengué, Olivier>, <Adherent: Lafarine, Francine>] >>> Adherent.objects.order_by('nom') [<Adherent: Lafarine, Francine>, <Adherent: Mengué, Olivier> ] >>> Adherent.objects.filter(nom='Mengué') [<Adherent: Mengué, Olivier>] >>> Adherent.objects.filter(nom__contains='ine') [<Adherent: Lafarine, Francine>]
Équivalent Perl :
Adherent->objects->filter('nom__contains' => 'ine');
qs = Adherent.object.all() .filter(naissance__gte=date(1966, 1, 1)) .filter(echeance__gte=date.today())
SQL :
SELECT * FROM adherent WHERE naissance >= '1966-01-01' AND echeance >= NOW
L'évaluation paresseuse permet des filtres conditionnels:
if affichage == 'N': qs = qs.order_by('naissance')
class Animateur(models.Model): adherent = models.OneToOneField(Adherent, verbose_name='adhérent') date_diplome = models.DateField('date du diplôme', auto_now_add=True, null=False, editable=True) parrain = models.ForeignKey('self', null=True)
class Rando(models.Model): CHOIX_RYTHMES = ( ('L', 'Lent'), ('M', 'Moyen'), ('S', 'Soutenu'), ('R', 'Rapide'), ) jour = models.DateField() titre = models.CharField("titre", maxlength=250, unique_for_date="jour") distance = models.IntegerField("distance (km)") rythme = models.CharField("rythme", maxlength=1, choices=CHOIX_RYTHMES) publication = models.DateField() descriptif = models.TextField() animateurs = models.ManyToManyField(Animateur, related_name='randos')
premier = Adherent.object.all()[0]
cinq_a_dix = Adherent.object.all()[5:10]
for a in Adherent.object.all(): print a
Animateur.parrain = None
minimiser les accès
optimisation des requêtes
appels explicites : save(), select_related()
Animateur.object.get(adherent__nom='Kelner').randos.all()
pas d'objets externes à importer, mais des méthodes simples directement appliquées aux objets
jointures transparentes si besoin
tous les objets accèdent à tous les autres